繁体   English   中英

关于应该把[无主自我]放在哪里的困惑

[英]Confusion about where should put the [unowned self]

我有一个保留周期,所以我的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正确提到的那样,问题与捕获self的时间有关。 事实上,此代码self被捕获两次:

  • 当外部闭包传递给handle方法时
  • 当内部闭包传递给async方法时(在handle闭包执行期间)

外部封闭件需要self将其传递到内部封闭件,否则内部封闭件将无法捕获它。

性质或保留周期如下: self (YADetailiViewController) - > subscription - > closure( handle parameter) - > self 要打破这个循环,就不能在那个(外部)闭包中保留self 这就是第二个代码示例有效的原因。

第二次捕获self (在内部闭包中)仅在外部闭包执行时发生并持续到执行async块 - 通常是很短的时间。

在第一个代码示例中,您没有打破循环。 self的第二次捕获不会发生,但第一次捕获(造成你的周期)仍然存在。

如果在视图控制器已被删除/释放时仍然可以调用handle闭包,那么按照@AdrianBobrowski的建议,您应该使用weak而不是unowned以防止可能的崩溃。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM