1. 程式人生 > >【Swift4.2】迴圈引用的例子講解

【Swift4.2】迴圈引用的例子講解

最近又想回顧下swift,現在版本已經到4.2了。。。想當時15年,我寫swift2.1的時候,我遇到了很多讓我感到尷尬的場景。。

https://www.cnblogs.com/rayshen/p/5038937.html

這邊部落格現在看起來還非常搞笑,但是當時確實是這樣。好在我之前說的這些問題,在後來的swift版本中,都已經給糾正過來了(感覺swift語言組也好水)……

 

這次要回顧的是迴圈引用,這個是老生常談的問題。在block和delegate中,如果兩個物件A和B,A強引用B,B又強引用A時,A的引用計數就會變成2,這樣就會造成A無法自動釋放。

 

看一段示例程式碼:

class Example{
    
    private var name = "123";
    
    
    /// 正確用法1
    lazy private var rightClosure1:()->() = { [unowned self] in
        print("name is \(self.name)")
    }
    
    /// 正確用法2
    lazy private var rightClosure2:()->() = { [weak self] in
        print("name is \(self?.name ?? 
"")") } /// 函式用法不存在該問題 private func commonFunction(){ print("name is \(self.name)") } /// 錯誤用法 lazy private var errorCycleClosure:()->() = { print("name is \(self.name)") } func startRight1() { rightClosure1() } func startRight2() { rightClosure2() } func startRight3() { commonFunction() } func startError() { errorCycleClosure() } deinit{ print(
"Example deinit") } } var example:Example? = Example() //呼叫正確例子1,example=nil後能正常銷燬 //example?.startRight1(); //呼叫正確例子2,example=nil後能正常銷燬 //example?.startRight2(); //呼叫正確例子3,example=nil後能正常銷燬(函式不存在迴圈引用問題) //example?.startRight3(); //呼叫錯誤例子,example=nil後沒有呼叫deinit,說明有殘留成員變數 example?.startError(); example=nil;

 

這裡面有幾個swift的知識點:

1.lazy的用法:所謂的lazy就是懶載入,在沒有被getter訪問時,他不進行初始化。在這裡,一個閉包初始化中訪問到self,因為self在此時還沒生成所以需要新增lazy修飾,使他們在被訪問到時才初始化。

2.[unowned self]和[weak self]和區別: [unowned self]呼叫closure的時候如果物件已經被釋放的話,會出現crash。

3.為什麼函式沒影響:因為函式在記憶體中只分配函式地址,不是一個物件。而閉包是一個物件,是個引用型別,會被例項物件所引用,如果閉包再引用例項物件本身,就會出現迴圈引用。