我不太了解如何在类中正确存储订阅者,以使它们持久化,但又不阻止对象被初始化。这是一个不会取消初始化对象的示例:
import UIKit
import Combine
class Test {
public var name: String = ""
private var disposeBag: Set<AnyCancellable> = Set()
deinit {
print("deinit")
}
init(publisher: CurrentValueSubject<String, Never>) {
publisher.assign(to: \.name, on: self).store(in: &disposeBag)
}
}
let publisher = CurrentValueSubject<String, Never>("Test")
var test: Test? = Test(publisher: publisher)
test = nil
当我将
assign
替换为sink
(在其中我正确声明了[weak self]
)时,它实际上确实可以正确初始化(可能是因为assign
以导致问题的方式访问self
)。例如,在使用
.assign
时如何防止强引用循环?谢谢
最佳答案
您可以将其.asign(to :)替换为接收器,其关闭中的[weak self]会破坏内存循环。在Playground尝试一下,看看有什么不同
final class Bar: ObservableObject {
@Published var input: String = ""
@Published var output: String = ""
private var subscription: AnyCancellable?
init() {
subscription = $input
.filter { $0.count > 0 }
.map { "\($0) World!" }
//.assignNoRetain(to: \.output, on: self)
.sink { [weak self] (value) in
self?.output = value
}
}
deinit {
subscription?.cancel()
print("\(self): \(#function)")
}
}
// test it!!
var bar: Bar? = Bar()
let foo = bar?.$output.sink { print($0) }
bar?.input = "Hello"
bar?.input = "Goodby,"
bar = nil
它打印
Hello World!
Goodby, World!
__lldb_expr_4.Bar: deinit
所以我们没有内存泄漏!
终于在forums.swift.org上,有人做了一个很好的小东西
extension Publisher where Self.Failure == Never {
public func assignNoRetain<Root>(to keyPath: ReferenceWritableKeyPath<Root, Self.Output>, on object: Root) -> AnyCancellable where Root: AnyObject {
sink { [weak object] (value) in
object?[keyPath: keyPath] = value
}
}
}
关于swift - 使用苹果公司的新Combine框架时如何防止强引用周期(.assign引起问题),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57980476/