And*_*tto 25 ios swift ios13 swiftui combine
如果我已将可取消集存储到 ViewController 中:
private var bag = Set<AnyCancellable>()
Run Code Online (Sandbox Code Playgroud)
其中包含多个订阅。
1 - 我应该在 deinit 中取消订阅吗?或者它会自动完成工作?
2 - 如果是这样,我如何取消所有存储的订阅?
bag.removeAll() is enough?
Run Code Online (Sandbox Code Playgroud)
还是我应该遍历集合并一一取消所有订阅?
for sub in bag {
sub.cancel()
}
Run Code Online (Sandbox Code Playgroud)
Apple 表示订阅一直有效,直到存储的 AnyCancellable 在内存中。所以我想解除分配可取消的bag.removeAll()应该足够了,不是吗?
And*_*ndy 13
在deinit您的视图控制器会从内存中删除。它的所有实例变量都将被释放。
文档Combine > Publisher > assign(to:on:)说:
AnyCancellable 实例。当您不再希望发布者自动分配属性时,在此实例上调用 cancel()。取消初始化此实例也将取消自动分配。
1 - 我应该在 deinit 中取消订阅吗?或者它会自动完成工作?
你不需要,它会自动完成这项工作。当您的 ViewController 被释放时,实例变量bag也将被释放。由于不再引用您的AnyCancellable's,作业将结束。
2 - 如果是这样,我如何取消所有存储的订阅?
不是这样。但通常您可能有一些想要开始和停止的订阅,例如viewWillAppear/ viewDidDissapear。在这种情况下,您的 ViewController 仍在内存中。
因此,在 中viewDidDissappear,您可以bag.removeAll()按自己的想法行事。这将删除引用并停止分配。
以下是一些您可以运行以查看.removeAll()实际操作的代码:
var bag = Set<AnyCancellable>()
func testRemoveAll() {
Timer.publish(every: 1, on: .main, in: .common).autoconnect()
.sink { print("===== timer: \($0)") }
.store(in: &bag)
Timer.publish(every: 10, on: .main, in: .common).autoconnect()
.sink { _ in self.bag.removeAll() }
.store(in: &bag)
}
Run Code Online (Sandbox Code Playgroud)
第一个计时器将每隔一秒触发一次并打印出一行。第二个计时器将在 10 秒后触发,然后调用bag.removeAll()。然后两个计时器发布者都将停止。
https://developer.apple.com/documentation/combine/publisher/3235801-assign
Mos*_*sam 11
如果你碰巧从你的 View 控制器订阅了一个发布者,你可能会捕获selfin sink,它会引用它,并且如果订阅者没有完成,不会让 ARC 稍后删除你的视图控制器,所以这是可取的弱地捕捉自我
所以而不是:
["title"]
.publisher
.sink { (publishedValue) in
self.title.text = publishedValue
}
.store(in: &cancellable)
Run Code Online (Sandbox Code Playgroud)
你应该使用[weak self]:
["title"]
.publisher
.sink { [weak self] (publishedValue) in
self?.title.text = publishedValue
}
.store(in: &cancellable)
Run Code Online (Sandbox Code Playgroud)
因此,当删除视图控制器时,您将不会有任何保留周期或内存泄漏。
sus*_*i99 10
我测试这段代码
let cancellable = Set<AnyCancellable>()
Timer.publish(every: 1, on: .main, in: .common).autoconnect()
.sink { print("===== timer: \($0)") }
.store(in: &cancellable)
cancellable.removeAll() // just remove from Set. not cancellable.cancel()
Run Code Online (Sandbox Code Playgroud)
所以我使用这个扩展。
import Combine
typealias CancelBag = Set<AnyCancellable>
extension CancelBag {
mutating func cancelAll() {
forEach { $0.cancel() }
removeAll()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15839 次 |
| 最近记录: |