1.自動引用計數實踐
-
ARC
初始化var reference1: Person? var reference2: Person? var reference3: Person? reference1 = Person(name: "John Appleseed") reference2 = reference1 reference3 = reference1 reference1 = nil reference2 = nil // 此時person物件還沒有釋放, reference3 = nil // 執行之後,物件進行釋放,列印deinit 方法 // 列印 “John Appleseed is being deinitialized 複製程式碼
2.類例項之間的迴圈強引用
-
Person 和Apartment
3.解決例項之間的迴圈強引用 --- 弱引用(weak reference)
-
Swift 提供了兩種辦法用來解決你在使用類的屬性時所遇到的迴圈強引用問題:弱引用(
weak
reference)和無主引用(unowned
reference )
4.解決例項之間的迴圈強引用 --- 無主引用(unowned reference )
- 在前面加上關鍵字unowned表示這是一個無主引用
- Person和Apartment的例子展示了兩個屬性的值都允許為nil,並會潛在的產生迴圈強引用。這種場景最適合用弱引用來解決。
- Customer和CreditCard的例子展示了一個屬性的值允許為nil,而另一個屬性的值不允許為nil,這也可能會產生迴圈強引用。這種場景最適合通過無主引用來解決。
5.無主引用以及隱式解析可選屬性
- 在這種場景中,兩個屬性都必須有值,並且初始化完成後永遠不會為nil。在這種場景中,需要一個類使用無主屬性,而另外一個類使用隱式解析可選屬性
- Country的建構函式呼叫了City的建構函式。然而,只有Country的例項完全初始化後,Country的建構函式才能把self傳給City的建構函式
- 為了滿足這種需求,通過在型別結尾處加上感嘆號(City!)的方式,將Country的capitalCity屬性宣告為隱式解析可選型別的屬性。這意味著像其他可選型別一樣,capitalCity屬性的預設值為nil,但是不需要展開它的值就能訪問它
- 由於capitalCity預設值為nil,一旦Country的例項在建構函式中給name屬性賦值後,整個初始化過程就完成了。這意味著一旦name屬性被賦值後,Country的建構函式就能引用並傳遞隱式的self。Country的建構函式在賦值capitalCity時,就能將self作為引數傳遞給City的建構函式
6.閉包引起的迴圈強引用
-
Swift 提供了一種優雅的方法來解決這個問題,稱之為閉包捕獲列表(closure capture list)
-
定義了一個類,一個懶載入屬性,懶載入屬性是個閉包,內部強引用了類的2個屬性
-
例項化物件
-
例項和閉包的引用關係如下:
7.解決閉包引起的迴圈強引用
-
在定義閉包時同時定義捕獲列表作為閉包的一部分,通過這種方式可以解決閉包和類例項之間的迴圈強引用
-
捕獲列表中的每一項都由一對元素組成,一個元素是weak或unowned關鍵字,另一個元素是類例項的引用(例如self)或初始化過的變數
(如delegate = self.delegate!)
。這些項在方括號中用逗號分開lazy var someClosure: (Int, String) -> String = { [unowned self, weak property= self. property!] (index: Int, stringToProcess: String) -> String in // 這裡是閉包的函式體 } 複製程式碼
8.使用弱引用和無主引用
- 在閉包和捕獲的例項總是互相引用並且總是同時銷燬時,將閉包內的捕獲定義為無主引用。
- 相反的,在被捕獲的引用可能會變為nil時,將閉包內的捕獲定義為弱引用。弱引用總是可選型別,並且當引用的例項被銷燬後,弱引用的值會自動置為nil。這使我們可以在閉包體內檢查它們是否存在。
- 注意如果被捕獲的引用絕對不會變為nil,應該用無主引用,而不是弱引用。