delegate 為什麼應該是 weak 型別而不是strong型別
阿新 • • 發佈:2019-01-30
delegate 為什麼應該是 weak 型別而不是strong型別
迴圈引用
物件a建立並引用了物件b.物件b建立並引用了物件c.物件c建立並引用了物件b.
這時候b和c的引用計數分別是2和1。當a不再使用b,呼叫release釋放對b的所有權,因為c還引用了b,所以b的引用計數為1,b不會被釋放。b不釋放,c的引用計數就是1,c也不會被釋放。從此,b和c永遠留在記憶體中。
打斷這種迴圈引用:
如果c引用b的時候是用weak型別弱引用,那麼a釋放b時,b的引用計數器變為0,b被釋放,c也被釋放。
一個例子:
;
兩個類互相強引用,referance counting永遠不會是0,一直會佔用記憶體,如果delegate是弱引用,那delegate釋放掉之後,這個類也可以被釋放
一個UITableViewController 物件a通過retain獲取了UITableView物件b的所有權,這個UITableView物件b的delegate又是a,如果這個delegate是retain方式的,那基本上就沒有機會釋放這兩個物件了。迴圈引用而產生的記憶體洩露也是Instrument無法發現的
所以delegate必須設定為weak型別
參考:
iOS 5 ARC完全指南.pdf
http://blog.csdn.net/diyagoanyhacker/article/details/6591593
http://www.cocoachina.com/ask/questions/show/93387
迴圈引用
物件a建立並引用了物件b.物件b建立並引用了物件c.物件c建立並引用了物件b.
這時候b和c的引用計數分別是2和1。當a不再使用b,呼叫release釋放對b的所有權,因為c還引用了b,所以b的引用計數為1,b不會被釋放。b不釋放,c的引用計數就是1,c也不會被釋放。從此,b和c永遠留在記憶體中。
打斷這種迴圈引用:
如果c引用b的時候是用weak型別弱引用,那麼a釋放b時,b的引用計數器變為0,b被釋放,c也被釋放。
一個例子:
// A.m中某處
B* b = [B alloc] init];
b.delegate = self
[self.view addSubview:b];
[b release];
原因1
delegate沒有必要是strong 是A負責建立B的,A的生命週期一定比B要長(B存在,A一定也存在;A存在,B不一定存在)也就是說在B(例項b)存在的時候,A(的例項)一定存在,所以沒有必要用retain將引用計數+1,assign足以
原因2
退一步假設存在這樣的情況:A比B先掛掉(A的例項先被release銷燬)那麼當然希望是[a relase]後,A中的方法不再被B呼叫,但是使用retain時候,A還是沒有被銷燬,so A中的方法仍會被B呼叫,但是assgin就無此問題
原因3
避免迴圈引用
另一個例子:
一個UITableViewController 物件a通過retain獲取了UITableView物件b的所有權,這個UITableView物件b的delegate又是a,如果這個delegate是retain方式的,那基本上就沒有機會釋放這兩個物件了。迴圈引用而產生的記憶體洩露也是Instrument無法發現的
所以delegate必須設定為weak型別
參考:
iOS 5 ARC完全指南.pdf
http://blog.csdn.net/diyagoanyhacker/article/details/6591593
http://www.cocoachina.com/ask/questions/show/93387