Swift Combine中的Set<AnyCancellable>是如何工作的?

7

我有一个 ViewModel,并定义了一组可处理的 Set,如下所示

class ViewModel { 


 private var disposables = Set<AnyCancellable>()

 func sync() { 
    repo.syncObjects()
            .handleEvents(receiveCancel: {
                print("Synced objects: CANCELED!")
            })
            .sink(receiveCompletion: { completion in
                switch completion {
                case .failure(let error):
                    print("Synced objects: \(error)")
                case .finished:
                    print("Synced objects: finished")
                }
            }) { objects in
                print("Synced objects: \(objects)")
            }.store(in: &disposables)
 }

  deinit { print("ViewModel deinit") }
}

我在SwiftUI视图的onAppear中调用了sync()。然后我快速切换屏幕,从SwiftUI视图引用的ViewModel被ARC解除引用,就像调用了deinit一样,但订阅似乎仍然存在,并且可释放的引用没有取消订阅,它从网络获取数据并将它们保存在Core Data中,并打印“已同步的对象:objects”、“已同步的对象:finished”。即使我停止几秒钟切换屏幕来完成旧请求,订阅仍然保持活动状态。
我应该手动取消AnyCancellable吗?难道它不会自动取消吗?

1
请展示 syncObjects 的实现方式。 - rob mayoff
你找到解决办法了吗?我也遇到了同样的问题。 - kalpesh
1个回答

9

但是我的同步(sync())网络请求似乎仍然在运行,并将结果存储在核心数据中,尽管已经离开了屏幕。我也调用并打印了deinit { print() }到控制台,因此表明我已经解除分配的对象。但是同时订阅中的receiveCancel没有被调用。在Instruments Allocations中,这个ViewModel似乎已经被分配?在那里,我有50个持久性、50个瞬态和100个总分配。它是SwiftUI视图中的@ObservableObject,所以如果视图发生更改,它应该被解除分配。 - Michał Ziobro
你能分享一下你具体的情况吗?嘿嘿嘿 - 93sauu
1
我发现有内存泄漏。我还在init()和deinit()中添加了打印语句,通常会有2个分配和1个释放,所以我认为这就是anycancellables没有被取消的原因。因此,我认为我需要搜索这个问题。 - Michał Ziobro
是的,这是最有可能的事情,因为如果某些泄漏内存保留了对对象的引用,则取消订阅的去初始化不会被调用 :) - 93sauu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接