一般的解釋是,考慮到對象的生命週期,您應該在unowned和weak之間進行選擇,但有時您可能仍然懷疑應該實際使用哪個,而且想知道unowned和weak哪個更好。閉包
衆所周知,Swift利用良好的舊ARC(自動引用計數)來管理內存,所以,正如咱們習慣使用Objective-C同樣,咱們必須經過明智地使用弱手動處理保留週期引用。函數
若是您不熟悉ARC,則只須要知道每一個引用類型實例都將具備與之關聯的引用計數(簡單整數值),這將用於保持對象實例當前的次數計數由變量或常數引用。一旦該計數器達到零,就會釋放實例,而且它們所擁有的內存和資源將再次可用。性能
每當兩個實例以某種方式相互引用時,您就有一個保留週期(例如,兩個類實例具備引用另外一個類實例的屬性,如同雙鏈表中的兩個相鄰節點實例同樣)會阻止這些實例被釋放,由於保留計數老是大於零的值。cdn
爲了解決這個問題,在Swift中以及在許多其餘語言中,引入了弱引用的概念,ARC不考慮這些引用,所以不會增長對象的保留計數。對象
考慮到弱引用不會阻止實例被釋放,所以必須始終記住,弱引用在任什麼時候候都不能再指向有效對象。blog
Swift有兩種弱引用:unowned和weak。生命週期
雖然它們用於相同的目的,但它們與您的實例生命週期相關的假設略有不一樣,而且具備不一樣的性能特徵。內存
在Objective-C中,遵循標準模式,您將在塊外聲明對該實例的弱引用,而後在塊內聲明對該實例的強引用,以便在塊執行期間獲取它。顯然,檢查引用是否仍然有效是必要的。資源
爲了幫助處理保留週期,Swift引入了一個新的構造來簡化並更明確地捕獲閉包內的外部變量,即捕獲列表。使用捕獲列表,您能夠在函數頂部聲明將用於指定應在內部建立哪一種引用的外部變量。作用域
1.當您不使用捕獲列表時,閉包將建立對外部做用域的值的強引用:
閉包內發生的修改將改變原始變量的值
2.使用捕獲列表,建立一個在閉包範圍內有效的新常量。
若是未指定捕獲修飾符,則常量只是原始值的副本,適用於值類型和引用類型。
在上面的例子中,咱們iCopy在調用以前聲明函數iStrong,而且當聲明函數初始化私有常量時。如您所見,當咱們調用第二個函數時,咱們仍然會打印原始值i1。
3.指定具備引用類型的外部變量的名稱以前weak或unowned以前,此常量將被初始化爲對原始值的弱引用,而且這種特定形式的捕獲是咱們用來中斷保留週期的形式。
使用unowned時 永遠不會爲nil 使用weak時 則是可選值
因此 若是這些對象的生命週期互不相關,也就是說,你不能保證哪一 個對象存在的時間會比另外一個⻓,那麼弱引用就是惟一的選擇。另外一種狀況下,若是你能夠保證非強引用對象擁有和強引用對象一樣或者更⻓的生命週期的話,unowned 引用一般會更方便一些。這是由於咱們能夠不須要處理可選值,並且變量將能夠被 let 聲明,而與之相對,弱引用必須被聲明爲可選的 var。一樣的生命週期是很常⻅的,特別是當 兩個物體擁有主從關係的時候。當主對象經過強引用控制子對象的生命週期,並且你能夠肯定 沒有其餘對象知道這個子對象的存在時,子對象對主對象的逆向引用就能夠是 unowned 引用。
unowned 引用要比 weak 引用少一些性能損耗,所以訪問一個 unowned 引用的屬性或者調用 它上面的方法都會稍微快一些;不過,這個因素應該只在性能很是重要的代碼路徑上才須要被 考慮。
unowned 引用帶來的很差的地方固然是若是你在生命週期的假設上犯了錯,那麼你的程序就將 崩潰。我的來講,我常常會在 unowned 也可使用的狀況下,仍是去選擇用 weak。weak 將強制咱們在全部使用的地方都去檢查引用是否依然有效。咱們可能會時不時地對一些 代碼進行重構,而這可能會致使咱們以前對於對象生命週期的假設失效。看你對哪一方面更重視