首先delegate要使用assign而不是retain,這個問題大家通過看iOS的api就可以了,最典型的是tabView里面的delegate和datasource都是用的assign。
一個對象沒必要管理自己delegate的生命周期,或者說沒必要擁有該對象,所以我們只要知道它的指針就可以了,用指針找到對象去調用方法,也就是委托實現的感覺。
或者我們換個角度,從內存管理方面也可以解釋這個問題。delegate的生命周期不需要讓該對象去控制,如果該對象對其使用retain很可能導致delegate所指向的對象無法正確的釋放。
循環引用所有的引用計數系統,都存在循環應用的問題。例如下面的引用關系:
對象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無法發現的,所以要特別小心。