首页 > 代码库 > 浅谈 关于ARC循环引用得问题
浅谈 关于ARC循环引用得问题
这段时间在研究关于ARC得循环引用导致变量不能释放,在此先介绍一本书英文书:
《Pro Multithreading and Memory Management for iOS and OS X with ARC, Grand Central Dispatch, and Blocks》
(《iOS与OS X多线程和内存管理》)
建议读英文原版,中文版看的我稀里糊涂的,后来被迫去看原版.这本书介绍了关于ARC的自动引用机制,这里的机制类似:当C语言的局部变量离开他的作用域之后就会被清除,这里的ARC也类似是这样的原理,如下面的代码一样,当离开{}之后obj会被nil。默认id是强指针
{/** You create an object and have ownership. */id __strong obj = [[NSObject alloc] init];/** The variable obj is qualified with __strong.* Which means, it has ownership of the object. */}/** Leaving the scope of variable obj, its strong reference disappears.* The object is released automatically.* Because no one has ownership, the object is disposed of.*/
不过有一种情况会导致在{}内的变量再离开作用域之后不会释放,这就是循环引用,下面我先贴一份没有循环引用的代码
//Test Class@interface Test : NSObject@property (nonatomic) id obj;- (void) setObj:(id)obj;@end@implementation Test- (void) setObj:(id)obj{ _obj = obj;}@end//Use Test Class- (void)viewDidLoad{ [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. id test0 = [[Test alloc]init]; id test1 = [[Test alloc]init]; self.t0 = test0; self.t1 = test1;}- (void) viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; NSLog(@"test0 is %p",self.t0); NSLog(@"test1 is %p",self.t1); NSLog(@"test0 obj is %p",self.t0.obj); NSLog(@"test1 obj is %p",self.t1.obj); NSLog(@"viewDidApperar!");}/* 这里的输出结果:2014-11-18 11:39:31.654 circular[27065:60b] test0 is (null)2014-11-18 11:39:31.654 circular[27065:60b] test1 is (null)2014-11-18 11:39:31.655 circular[27065:60b] test0 obj is (null)2014-11-18 11:39:31.655 circular[27065:60b] test1 obj is (null)2014-11-18 11:39:31.655 circular[27065:60b] viewDidApperar! */
现在我贴一下存在循环引用的代码,这个时候局部变量的强指针相互引用,这里我们可以看见Test0的obj指向Test1,而Test1的obj指向Test0,导致释放不了.
//Test Class@interface Test : NSObject@property (nonatomic) id obj;- (void) setObj:(id)obj;@end@implementation Test- (void) setObj:(id)obj{ _obj = obj;}@end//Use Test Class- (void)viewDidLoad{ [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. id test0 = [[Test alloc]init]; id test1 = [[Test alloc]init]; [test0 setObj:test1]; [test1 setObj:test0]; self.t0 = test0; self.t1 = test1;}- (void) viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; NSLog(@"test0 is %p",self.t0); NSLog(@"test1 is %p",self.t1); NSLog(@"test0 obj is %p",self.t0.obj); NSLog(@"test1 obj is %p",self.t1.obj); NSLog(@"viewDidApperar!");}/*这里的输出结果:2014-11-18 11:42:35.555 circular[27654:60b] test0 is <Test: 0x8c8fe20>2014-11-18 11:42:35.556 circular[27654:60b] test1 is <Test: 0x8cf7c20>2014-11-18 11:42:35.556 circular[27654:60b] test0 obj is <Test: 0x8cf7c20>2014-11-18 11:42:35.556 circular[27654:60b] test1 obj is <Test: 0x8c8fe20>2014-11-18 11:42:35.558 circular[27654:60b] viewDidApperar!*/
一般的解决办法就是weak obj,代码如下:
//Test Class@interface Test : NSObject@property (nonatomic,weak) id obj;- (void) setObj:(id)obj;@end@implementation Test- (void) setObj:(id)obj{ _obj = obj;}@end//Use Test Class- (void)viewDidLoad{ [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. id test0 = [[Test alloc]init]; id test1 = [[Test alloc]init]; [test0 setObj:test1]; [test1 setObj:test0]; self.t0 = test0; self.t1 = test1;}- (void) viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; NSLog(@"test0 is %p",self.t0); NSLog(@"test1 is %p",self.t1); NSLog(@"test0 obj is %p",self.t0.obj); NSLog(@"test1 obj is %p",self.t1.obj); NSLog(@"viewDidApperar!");}/*这里的输出结果:2014-11-18 11:46:19.803 circular[28360:60b] test0 is (null)2014-11-18 11:46:19.804 circular[28360:60b] test1 is (null)2014-11-18 11:46:19.804 circular[28360:60b] test0 obj is (null)2014-11-18 11:46:19.805 circular[28360:60b] test1 obj is (null)2014-11-18 11:46:19.805 circular[28360:60b] viewDidApperar!*/
浅谈 关于ARC循环引用得问题
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。