天天看點

為什麼很多内置類如UITableViewController的delegate屬性都是assign而不是retain的

問:為什麼很多内置類如UITableViewController的delegate屬性都是assign而不是retain的?答:會引起循環引用。

這裡delegate我們隻是想得到實作了它delegate方法的對象,然後拿到這個對象的指針就可以了,我們不期望去改變它或者做别的什麼操作,是以我們隻要用assign拿到它的指針就可以了。

而用retain的話,計數器加1。我們有可能在别的地方期望釋放掉delegate這個對象,然後通過一些判斷比如說它是否已經被釋放,做一些操作。但是實際上它retainCount還是1,沒有被釋放掉,要在UITableViewController的dealloc裡面才被釋放掉(這裡我隻是舉個例子,一般retain的對象都是在dealloc裡被釋放)。這裡就會造成一些問題出現。

而如果你确定不會有沖突的問題出現的話,或者你也希望用到delegate的這個對象,直到你不用它為止,那麼用retain也未嘗不可,隻是需要最後release一次。

會引起循環引用。

循環引用

所有的引用計數系統,都存在循環應用的問題。例如下面的引用關系:

對象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永遠留在記憶體中。

這種情況,必須打斷循環引用,通過其他規則來維護引用關系。比如,我們常見的delegate往往是assign方式的屬性而不是retain方式的屬性,指派不會增加引用計數,就是為了防止delegation兩端産生不必要的循環引用。如果一個UITableViewController 對象a通過retain擷取了UITableView對象b的所有權,這個UITableView對象b的delegate又是a, 如果這個delegate是retain方式的,那基本上就沒有機會釋放這兩個對象了。自己在設計使用delegate模式時,也要注意這點。

因為循環引用而産生的記憶體洩露也是Instrument無法發現的,是以要特别小心。

一些和記憶體管理相關的有用内容: