Skip to content

Commit fb0d283

Browse files
authored
Merge pull request #113 from growthbook/fix/leak-ios18.5
**Root Cause:** Retain cycle in `FeaturesViewModel.connectBackgroundSync()`: - `SSEHandler.onDisconnect` closure was capturing `streamingUpdate` strongly - Created circular reference preventing proper deallocation - iOS 18.5's stricter memory management caught this issue
2 parents 4db1c3b + 8c5a94d commit fb0d283

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

Sources/CommonMain/Features/FeaturesViewModel.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class FeaturesViewModel {
1616
var encryptionKey: String?
1717
/// Caching Manager
1818
let manager: CachingLayer
19+
/// SSE Handler for background sync
20+
internal var sseHandler: SSEHandler?
1921

2022
init(delegate: FeaturesFlowDelegate, dataSource: FeaturesDataSource, cachingManager: CachingLayer) {
2123
self.delegate = delegate
@@ -26,20 +28,30 @@ class FeaturesViewModel {
2628

2729
func connectBackgroundSync(sseUrl: String) {
2830
guard let url = URL(string: sseUrl) else { return }
31+
32+
// Disconnect existing connection if any
33+
sseHandler?.disconnect()
34+
2935
let streamingUpdate = SSEHandler(url: url)
36+
sseHandler = streamingUpdate
37+
3038
streamingUpdate.addEventListener(event: "features") { [weak self] id, event, data in
3139
guard let jsonData = data?.data(using: .utf8) else { return }
3240
self?.prepareFeaturesData(data: jsonData)
3341
}
3442
streamingUpdate.connect()
3543

36-
streamingUpdate.onDissconnect { _, shouldReconnect, _ in
44+
streamingUpdate.onDissconnect { [weak streamingUpdate] _, shouldReconnect, _ in
3745
if let shouldReconnect = shouldReconnect, shouldReconnect {
38-
streamingUpdate.connect()
46+
streamingUpdate?.connect()
3947
}
4048
}
4149
}
4250

51+
deinit {
52+
sseHandler?.disconnect()
53+
}
54+
4355
private func fetchCachedFeatures(logging: Bool = false) {
4456
// Check for cache data
4557
if let data = manager.getContent(fileName: Constants.featureCache) {

0 commit comments

Comments
 (0)