博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈 关于ARC循环引用得问题
阅读量:7282 次
发布时间:2019-06-30

本文共 5343 字,大约阅读时间需要 17 分钟。

这段时间在研究关于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 %@",self.t0);    NSLog(@"test1 is %@",self.t1);    NSLog(@"test0 obj is %@",self.t0.obj);    NSLog(@"test1 obj is %@",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!    */

/*

  • *  Leaving the scope of variable test0, its strong reference disappears.

  • *  object A is released automatically. *

  • *  Leaving the scope of variable test1, its strong reference disappears.

  • *  object B is released automatically.

    *

  • *  At this moment, obj_ of object B has a strong reference to object A. *

  • *  At this moment, obj_ of object A has a strong reference to object B. *

  • *  memory leaked!! */ 

 

 

现在我贴一下存在循环引用的代码,这个时候局部变量的强指针相互引用,这里我们可以看见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 %@",self.t0);    NSLog(@"test1 is %@",self.t1);    NSLog(@"test0 obj is %@",self.t0.obj);    NSLog(@"test1 obj is %@",self.t1.obj);    NSLog(@"viewDidApperar!");}/*这里的输出结果:2014-11-18 11:42:35.555 circular[27654:60b] test0 is 
2014-11-18 11:42:35.556 circular[27654:60b] test1 is
2014-11-18 11:42:35.556 circular[27654:60b] test0 obj is
2014-11-18 11:42:35.556 circular[27654:60b] test1 obj is
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 %@",self.t0);    NSLog(@"test1 is %@",self.t1);    NSLog(@"test0 obj is %@",self.t0.obj);    NSLog(@"test1 obj is %@",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!*/

 

 

那么我们现在来了解一下为什么使用weak之后就会解除循环引用呢?

当我们直接写  id __weak obj = [[NSObject alloc] init];  

会提示警告:因为使用了weak,所以obj并不持有该对象,那么[[NSObject alloc] init]被创建之后没有人持有它,那么它就会被释放,所以这里应该修改成,当执行{}之后 obj0 和 obj1 都会被释放,因为当obj0被释放之后,obj1会变成nil因为weak引用不持有对象,当引用对象的强指针消失时,weak声明的指针也会自动null

{/** You create an object and have ownership. */id __strong obj0 = [[NSObject alloc] init];/** The variable obj0 is qualified with __strong.* Which means, it has ownership of the object. */id __weak obj1 = obj0;/** variable obj1 has a weak reference of the created object */} /** Leaving the scope of variable obj0, its strong reference disappears.* The object is released automatically.* Because no one has ownership, the object is discarded. */

 

那么下面这个例子就说明了weak会自动null

id __weak obj1; //__strong ,__weak 声明的变量会自动设置成为nil,这里等同于 id __weak obj1 = nil; 
{id __strong obj0 = [[NSObject alloc] init];obj1 = obj0;NSLog(@"A: %@", obj1); }NSLog(@"B: %@", obj1);The result is:A: 
B: (null)

 

转载于:https://www.cnblogs.com/zuopeng/p/4105356.html

你可能感兴趣的文章
想换工作?阿里技术战略部招人啦!
查看>>
果粉的福音!SteamVR将推出OSX和Linux测试版本
查看>>
Python面试真实笔试题总结(附加实现答案)
查看>>
matlab读取csv文件数据并绘图
查看>>
Fortinet 携手中信国际电讯CPC在亚太地区扩展安全托管服务
查看>>
Mysql 数据库单机多实例部署手记
查看>>
亚太区各城市生活成本大比拼
查看>>
六西格玛管理——《可以量化的管理学》
查看>>
wdlinux 一键安装
查看>>
Jenkins可用环境变量列表以及环境变量的使用(Shell/Command/Maven/Ant)
查看>>
威胁猎手养成
查看>>
idea2017.3卡死的坑
查看>>
CUBA Platform 开发者手册中文版发布 ,企业级应用开发平台
查看>>
Spring集成redis(Spring Data Redis)
查看>>
php常用Stream函数集介绍
查看>>
Atom打开大文件卡死的问题替代方案
查看>>
区块链集体癫狂的背后是互联网行业缺乏创新的焦虑
查看>>
揭示汽车制造行业未来,尽在广州自动化展!
查看>>
重新安装yum(以centos6.6为例)
查看>>
大数据在商业化浪潮中大步前进,但网络安全迫在眉睫
查看>>