在之前的一片文章中,我們介紹了數組操作對象的時候引用問題以及自動釋放池的概念:
今天我們繼續來看一下引用計數中一個痛疼的問題:循環引用
關於循環引用的問題,這裡就不做太多解釋了,就是多個對象之間相互引用,形成環狀。
來看一個具體的例子:
Dog類和Person類之間相互引用
Dog.h
// // Dog.h // 29_CyclePointer // // Created by jiangwei on 14-10-13. // Copyright (c) 2014年 jiangwei. All rights reserved. // #import#import Person.h @interface Dog : NSObject //這裡不用retain,如果使用retain的話,會形成循環引用 @property(nonatomic,assign,readwrite) Person *person; - (void)dealloc; @end
Dog.m
// // Dog.m // 29_CyclePointer // // Created by jiangwei on 14-10-13. // Copyright (c) 2014年 jiangwei. All rights reserved. // #import Dog.h @implementation Dog - (void)dealloc{ //[_person release]; NSLog(@dog dealloc); [super dealloc]; } @endDog類中有一個Person類型的屬性
Person.h
// // Person.h // 29_CyclePointer // // Created by jiangwei on 14-10-13. // Copyright (c) 2014年 jiangwei. All rights reserved. // #import@class Dog; @interface Person : NSObject @property(nonatomic,retain,readwrite) Dog *dog; - (void)dealloc; @end
// // Person.m // 29_CyclePointer // // Created by jiangwei on 14-10-13. // Copyright (c) 2014年 jiangwei. All rights reserved. // #import Person.h #import Dog.h @implementation Person - (void)dealloc{ [_dog release]; NSLog(@Person dealloc); [super dealloc]; } @endPerson類中有Dog類型的屬性
看一下測試代碼
main.m
// // main.m // 29_CyclePointer // // Created by jiangwei on 14-10-13. // Copyright (c) 2014年 jiangwei. All rights reserved. // #import我們分別定義了一個Person對象和Dog對象,然後相互引用了,但是當我們調用他們的release方法的時候,這兩個對象並沒有被釋放#import Dog.h #import Person.h //循環引用 //是一個很麻煩的一件事,完全靠經驗 int main(int argc, const char * argv[]) { Person *p = [[Person alloc] init]; Dog *dog = [[Dog alloc] init]; [p setDog:dog];//dog計數:2 [dog setPerson:p];//person計數:2 [p release]; //person計數:1 [dog release];//dog計數:1 //沒有釋放的原因是dealloc方法中沒有被執行,裡面的釋放代碼也就沒執行了,dog和person各自在等待,形成環狀了 //解決版本就是切斷他們之間的聯系 //@property中不使用retain,使用assgin NSLog(@is over); return 0; }
原因很簡單:
person和dog的相互引用了,當執行release方法的時候引用計數都還是1,所以就不會調用dealloc方法了
dealloc方法中沒有被執行,裡面的釋放代碼也就沒執行了,dog和person各自在等待,形成環狀了
解決的辦法是:
切斷他們之間的聯系
在一方中定義屬性的時候,@property中不使用retain,使用assgin
同時在dealloc方法中不再調用release方法了
上面的例子中,我們可以看到Dog類中就是使用assgin