2016-08-14 81 views
8

這裏是我的自定義視圖:斯威夫特保留週期解釋

class CustomVIew: UIView { 

    deinit { 
     print("custom view deinit") 
    } 

    var onTapViewHandler: (()->Void)? 
} 

和視圖控制器:

class ViewControllerB: UIViewController { 

    var customView: CustomVIew! 

    deinit { 
     print("B deinit") 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let customView = CustomVIew() 
     customView.onTapViewHandler = { [unowned self] in 
      self.didTapBlue() 
     } 
     customView.frame = CGRect(x: 50, y: 250, width: 200, height: 100) 
     customView.backgroundColor = UIColor.blueColor() 
     view.addSubview(customView) 

     self.customView = customView 

    } 

    func didTapBlue() { 

    } 
} 

當控制器從導航堆棧中彈出,一切都很好:

B deinit 
custom view deinit 

但是當我替換此代碼時:

customView.onTapViewHandler = { [unowned self] in 
    self.didTapBlue() 
} 

與此:

customView.onTapViewHandler = didTapBlue 

那麼,沒有打印在控制檯上。 CustomView和ViewController沒有發佈,爲什麼?

爲什麼customView.onTapViewHandler = didTapBlue捕獲對self的引用?

+0

你知道爲什麼已經不是嗎?你的標題說它是保留圈...通過打印檢查引用計數:print(CFGetRetainCount(object)) – Surely

+0

@你確實建議'CFGetRetainCount'來解決'retain'的問題。但有一個原因,保留'已被棄用:這不是一個好的解決方案。 – Abizern

+0

這只是一種檢查方法。我的意思是你可以輸出視圖控制器被引用的引用數量,以便你知道「customView」是否對視圖控制器有很強的參考。如果有,則有一個保留週期。因爲它有一個保留週期,所以這兩個對象不能自動銷燬。 – Surely

回答

4

如果將[unowned self]捕獲列表添加到閉包中,該視圖將持有對self的弱引用,並且self對該視圖持有強烈的引用。

由於沒有任何關於self的強烈參考,當彈出視圖控制器時,可以取消初始化self。在self被初始化之後,沒有任何東西對視圖有強烈的參考,所以也被去初始化。

如果您刪除捕獲列表,self對該視圖持有強烈的參考,並且該視圖對self有強烈的參考。這意味着爲了取消初始化self,視圖必須首先被初始化(這將打破強引用)。但爲了使視圖被初始化,視圖控制器必須首先被去初始化以打破對視圖的強引用。但是,除非您取消初始化視圖控制器,否則無法打破視圖的強烈引用。除非取消初始化視圖,否則不能分解對視圖控制器的強引用。

請參閱?我們已經陷入了無限循環!所以視圖和視圖控制器都不會被初始化!

4

Swift函數是一種閉包。就像閉包(目標c中的塊)功能可以捕獲參考。

customView.onTapViewHandler = didTapBlue得到執行時引用selfViewControllerB引用在這種情況下將被函數調用捕獲。

同時ViewControllerB的觀點對CustomVIew持有強烈的參考,因此它使保留週期。

關於使用unownedApple document說:

弱和無主引用啓用的參考週期 一個實例來指代其他實例,而無需保持強抱上它。 然後,實例可以互相引用,而不會創建強大的參考週期 。

這意味着沒有循環引用和保留週期。

+0

thanks.I只是不明白爲什麼'customView.onTapViewHandler = didTapBlue'執行會捕獲'self''參考,你能告訴我嗎? –

+0

'didTapBlue'是'self.didTapBlue'。所以'customView'應該保存對'didTapBlue'的引用,只有這樣它才能執行該函數。如你所知,didTapBlue如果沒有對象的引用就無法生存。所以關閉,塊和方法爲實例添加了強大的參考 – renjithr

+0

哦!我懂了。非常感謝你!^ - ^ –