簡體   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