2017-08-09 173 views
1

我已經閱讀了關於什麼時候應該使用[weak self][unowned self]關閉的幾個關於StackOverflow的討論。什麼時候我們不應該使用[weak self]和[unowned self]?

但是,有什麼情況我們不需要使用既不是他們,因爲當我們只是在閉包中明確使用self時,Swift不會顯示任何錯誤或警告。

例如,我們應該在這裏使用weak還是unowned

UIView.animate(withDuration: 0.3) { 
    self.view.alpha = 0.0 
} 
+1

在任何情況下,**沒有提及**何時使用**的答案**? –

+1

另請參閱[強封閉循環參考](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097 -CH20-ID56)Swift編程語言指南的一部分。 –

回答

1

如果閉合會導致強參考週期,則需要使用[weak self]或[unowned self]。

此,如果你分配封蓋的自我的屬性,可能會發生,你指的自我蓋子本身的屬性。閉包是引用類型,因此基本上相同的規則適用於強引用,如同使用普通類一樣。

至於你的例子,不需要[weak self][unowned self],因爲你沒有把閉包分配給self引用的類中的變量,所以不會有強的參考週期。

有關更多信息,請查閱Swift編程語言指南的Strong Reference Cycles for Closures部分。下面是從當強參考週期可以通過閉合而引起的所提到的鏈接的示例:

class HTMLElement { 

    let name: String 
    let text: String? 

    lazy var asHTML:() -> String = { 
     if let text = self.text { 
      return "<\(self.name)>\(text)</\(self.name)>" 
     } else { 
      return "<\(self.name) />" 
     } 
    } 

    init(name: String, text: String? = nil) { 
     self.name = name 
     self.text = text 
    } 

    deinit { 
     print("\(name) is being deinitialized") 
    } 

} 

沒有[unowned self]asHTML封閉,強大的參考週期將通過分配給asHTML封閉引起的。將asHTML更改爲以下解決方案可解決此問題:

lazy var asHTML:() -> String = { 
    [unowned self] in 
    if let text = self.text { 
     return "<\(self.name)>\(text)</\(self.name)>" 
    } else { 
     return "<\(self.name) />" 
    } 
} 
+0

等待,但這2個asHTML var實現有什麼區別? – Legonaftik

+0

不小心將'[unowned self]'從正確的實現中排除,現在修復它。 –

1

這有點意見爲主,所以我給我的意見:)

我一般將它基於同步。如果閉包是異步的,則在呼叫閉包機時呼叫實例可能不再存在,因此應使用[weak self]。如果一個閉包是同步的,這是不必要的,捕獲一個強大的參考是好的。

可以擴大到包括關閉在那裏你可以合理地預期,當它被稱爲(例如,您的觀看動畫時)的情況下仍然有效,但是請注意,這使得一個假設,即關閉和你對它的使用將保持不變,所以它在理論上可能在未來的某個時候突破。這不太安全,並使未來的維護更加困難/危險。

對於像UIView.animate這樣既定且可預測的API,我個人傾向於爲了簡潔而使用強大的自我,但這是您需要自己做的評估,它取決於使用情況。

同樣如註釋中所述,函數閉包也是如此。將閉包分配給另一個變量的屬性有一組不同的問題。另外,我已經採用弱引用閉包的方法,簡單地調用我的類型中的另一種方法,例如,

thing.doSomethingWithAClosure() { [weak self] 
    self?.doSomething() 
} 

它簡化了邏輯,同時執行更多的功能/模塊化代碼。

相關問題