我有一个保留周期,所以我的viewcontroller的deinit将不会被调用,我正在尝试解决这个问题,我添加[unowned self],但是我不太确定在我的情况下将无主的放在哪里:
情况1
class YADetailiViewController: UIViewController {
var subscription: Subscription<YAEvent>?
override func viewDidLoad() {
super.viewDidLoad()
if let query = self.event.subscribeQuery() {
self.subscription = Client.shared.subscribe(query)
self.subscription?.handle(Event.updated) {
query, object in
DispatchQueue.main.async {
[unowned self] in// Put unowned here won't break the cycle, but it does compile and run
self.pageViewLabel.text = String(object.pageViews) + " VIEW" + ((object.pageViews > 1) ? "S" : "")
}
}
}
}
}
案例2
override func viewDidLoad() {
super.viewDidLoad()
if let query = self.event.subscribeQuery() {
self.subscription = Client.shared.subscribe(query)
self.subscription?.handle(Event.updated) {
[unowned self] query, object in // Put unowned breaks the cycle, and deinit is called
DispatchQueue.main.async {
self.pageViewLabel.text = String(object.pageViews) + " VIEW" + ((object.pageViews > 1) ? "S" : "")
}
}
}
}
我很好奇这两种情况之间的区别是什么,为什么一种有效而另一种无效
最佳答案 实际上,正如@matt正确提到的那样,问题与捕获自我的时间有关.事实上,此代码自我被捕获两次:
>当外部闭包传递给handle方法时
>当内部闭包传递给异步方法时(在句柄闭包执行期间)
外部封闭件需要自我将其传递到内部封闭件,否则内部封闭件将无法捕获它.
性质或保留周期如下:self(YADetailiViewController) – >订阅 – >闭包(句柄参数) – >自.要打破这个循环,就不能在那个(外部)闭包中保留自我.这就是第二个代码示例有效的原因.
第二次捕获self(在内部闭包中)仅在外部闭包执行时发生并持续到执行异步块 – 通常是很短的时间.
在第一个代码示例中,您没有打破循环.自我的第二次捕获不会发生,但第一次捕获(造成你的周期)仍然存在.
如果在视图控制器已被删除/释放时仍然可以调用句柄闭包,那么按照@AdrianBobrowski的建议,您应该使用弱而不是无主,以防止可能的崩溃.