对象之间的循环引用
两个对象A、B,有可能会出现一种特殊的情况:A中包含B的实例变量;B中又包含A的实例变量,如果两个实例变量都是强引用(A有B实例变量的所有权,B也有A的实例变量的所有权),然后再两个对象销毁时,会出现A、B都不能正常销毁的情况。
类A:
// A.h // 02-循环引用 // // Created by ma c on 15/8/14. // Copyright (c) 2015年. All rights reserved. // #import <Foundation/Foundation.h> //类的前向声明(只存在包含关系中) @class B; @interface A : NSObject @property(nonatomic,retain)B *b;//A获得b对象的所有权 @end ------------------------------------------------------- // A.m // 02-循环引用 // // Created by ma c on 15/8/14. // Copyright (c) 2015年. All rights reserved. // #import "A.h" #import "B.h" @implementation A -(void)dealloc { [_b release]; NSLog(@"A dealloc"); [super dealloc]; } @end
类B:
// B.h // 02-循环引用 // // Created by ma c on 15/8/14. // Copyright (c) 2015年. All rights reserved. // #import <Foundation/Foundation.h> @class A; @interface B : NSObject @property(nonatomic,retain)A *a;//B获得a对象所有权 @end ------------------------------------------------------------ // B.m // 02-循环引用 // // Created by ma c on 15/8/14. // Copyright (c) 2015年. All rights reserved. // #import "B.h" #import "A.h" @implementation B -(void)dealloc { //[_a release]; NSLog(@"B dealloc"); [super dealloc]; } @end
主函数测试:
1 // main.m 2 // 02-循环引用 3 // 4 // Created by ma c on 15/8/14. 5 // Copyright (c) 2015年. All rights reserved. 6 // 7 8 #import <Foundation/Foundation.h> 9 #import "A.h" 10 #import "B.h" 11 int main(int argc, const char * argv[]) 12 { 13 @autoreleasepool 14 { 15 //测试对象间的循环引用 16 A *a = [[A alloc]init]; 17 B *b = [[B alloc]init]; 18 19 [a setB:b]; 20 [b setA:a]; 21 22 [a release]; 23 [b release]; 24 25 } 26 return 0; 27 }
测试结果是:
Program ended with exit code: 0
上面的结果明显的a和b对象都没有成功释放内存而销毁,因为它们都是retain获得对方的所有权,谁都不肯先释放;
处理方法:将双方任意一方的对象属性retain做一下修改即可,改为assign
修改后测试结果如下:
2015-08-14 16:32:27.210 02-循环引用[1427:94559] A dealloc 2015-08-14 16:32:27.211 02-循环引用[1427:94559] B dealloc Program ended with exit code: 0