【问题标题】:Swift Combine how Set<AnyCancellable> works?Swift 结合 Set<AnyCancellable> 如何工作?
【发布时间】:2020-09-05 09:45:14
【问题描述】:

我有这样定义的一次性 Set 的 ViewModel

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 一样,但订阅似乎仍然存在,一次性引用不会取消订阅它从网络获取数据并将它们保存在核心数据中并打印同步对象:对象, 同步对象:完成。即使我停止切换屏幕几秒钟以完成旧请求,它仍然保持活力。

我应该手动取消 AnyCancellable 吗?不应该自动取消吗?

【问题讨论】:

  • 告诉我们syncObjects是如何实现的。

标签: swift subscription combine disposable


【解决方案1】:

不,您不需要取消任何可取消的,因为这种对象在取消初始化时会调用方法cancel。所以你的代码是正确的。

Apple 的 AnyCancellable 文档:

An AnyCancellable instance automatically calls cancel() when deinitialized

AnyCancellable

【讨论】:

  • 但我在 sync() 中的网络请求似乎仍然存在,并且尽管离开屏幕,但仍将结果存储在核心数据中。我还调用了 deinit { print() } 并打印到控制台,因此它表明我已释放对象。但同时没有调用订阅中的receiveCancel。在 Instrutents Allocations 中,这个 ViewModel 似乎被分配了?我有 50 个持久性 50 个瞬态和 100 个总分配。它是 SwiftUI 视图中的 @ObservableObject,所以如果视图被更改,我认为它应该被释放
  • 你能分享一下你的具体情况吗? jejeje
  • 我发现有内存泄漏。我还在 init() 和 deinit() 中添加了 print 语句,通常有 2 个分配和 1 个释放,所以我认为这就是 anycancellables 没有被取消的原因。所以我认为我需要搜索这个问题而不是
  • 是的,这是最可能的事情,因为如果某些泄漏内存保持对对象的引用,则不会调用取消初始化的对象:)
猜你喜欢
  • 2020-03-19
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
  • 1970-01-01
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多