1. 程式人生 > >delegate 為什麼應該是 weak 型別而不是strong型別

delegate 為什麼應該是 weak 型別而不是strong型別

delegate 為什麼應該是 weak 型別而不是strong型別


迴圈引用
物件a建立並引用了物件b.物件b建立並引用了物件c.物件c建立並引用了物件b.
這時候bc的引用計數分別是21。當a不再使用b,呼叫release釋放對b的所有權,因為c還引用了b,所以b的引用計數為1b不會被釋放。b不釋放,c的引用計數就是1c也不會被釋放。從此,bc永遠留在記憶體中。

打斷這種迴圈引用:
如果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將引用計數+1assign足以

原因2

退一步假設存在這樣的情況:AB先掛掉(A的例項先被release銷燬)那麼當然希望是[a relase]後,A中的方法不再被B呼叫,但是使用retain時候,A還是沒有被銷燬,so A中的方法仍會被B呼叫,但是assgin就無此問題

原因3

避免迴圈引用

兩個類互相強引用,referance counting永遠不會是0,一直會佔用記憶體,如果delegate是弱引用,那delegate釋放掉之後,這個類也可以被釋放

另一個例子:


一個UITableViewController 物件a通過retain獲取了UITableView物件b的所有權,這個UITableView物件bdelegate又是a如果這個delegateretain方式的,那基本上就沒有機會釋放這兩個物件了。迴圈引用而產生的記憶體洩露也是Instrument無法發現的

所以delegate必須設定為weak型別




參考:
iOS 5 ARC完全指南.pdf 
http://blog.csdn.net/diyagoanyhacker/article/details/6591593

http://www.cocoachina.com/ask/questions/show/93387