浅谈 关于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 %@",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 <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 %@",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: <NSObject: 0x753e180> B: (null)
浅谈 关于ARC循环引用得问题的更多相关文章
- 浅谈Java中的引用
在Java语言中,引用是指,某一个数据,代表的是另外一块内存的的起始地址,那么我们就称这个数据为引用. 在JVM中,GC回收的大致准则,是认定如果不能从根节点,根据引用的不断传递,最终指向到一块内存区 ...
- 浅谈ThreadPool 线程池(引用)
出自:http://www.cnblogs.com/xugang/archive/2010/04/20/1716042.html 浅谈ThreadPool 线程池 相关概念: 线程池可以看做容纳线程的 ...
- 浅谈Spring解决循环依赖的三种方式
引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下Spring是如果解决循环依赖的. 第一种: ...
- JS浅谈原始值与引用值操作
值的操作分为三大类:复制,传递,比较 一:复制 原始值 let a = 10; let b = a; 注释:2018-7-30 17:33:49 1 原始类型的值都是存放在栈内存当中,所以他们的赋值操 ...
- 浅谈js for循环输出i为同一值的问题
问题再现 最近开发中遇到一个问题,为什么每次输出都是5,而不是点击每个p,就alert出对应的1,2,3,4,5. <html> <head> <meta http- ...
- 浅谈js for循环输出i为同一值的问题(闭包解决)
1.最近开发中遇到一个问题,为什么每次输出都是5,而不是点击每个p,就alert出对应的1,2,3,4,5. <html> <head> <meta http-equiv ...
- Spring5.0源码学习系列之浅谈循环依赖问题
前言介绍 附录:Spring源码学习专栏 在上一章的学习中,我们对Bean的创建有了一个粗略的了解,接着本文浅谈Spring循环依赖问题,这是一个面试比较常见的问题 1.什么是循环依赖? 所谓的循环依 ...
- 浅谈Java中的对象和引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
- block使用小结、在arc中使用block、如何防止循环引用
引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题: [小测试]你真的知道blocks在Objective-C中是怎么工作的吗 ...
随机推荐
- eval(function(p,a,c,k,e,r)解密程序
以eval(function(p,a,c,k,e,r){e=function(c)开头的js文件是经过加密的 使用下面方法可以对js文件进行加密.解密 步骤:1.新建html页面,内容如下列代码 2. ...
- 服务器启动时Webapp的web.xml中配置的加载顺序
一 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Ser ...
- 问题:只能在执行 Render() 的过程中调用 RegisterForEventValidation;结果:只能在执行 Render() 的过程中调用 RegisterForEventValidation
只能在执行 Render() 的过程中调用 RegisterForEventValidation 当在导出Execl或Word的时候,会发生只能在执行 Render() 的过程中调用 Register ...
- xcopy 命令行
https://www.cnblogs.com/yang-hao/p/6003308.html xcopy-参数详解 XCOPY——目录复制命令 1.功能:复制指定的目录和目录下的所有文件连同目 ...
- python request (1) 环境
环境准备 requests httpbin virtualenv pip python 安装 #mkdir /home/requests #yum install -y python-pip ...
- Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!
Eclipse 编译没问题,但是运行就出现这个报错:Unknown error: Unable to build: the file dx.jar was not loaded from the SD ...
- 支撑矢量机SVM
1.线性SVM 首先,回顾一下SVM问题的定义,如下: 线性约束很烦,不方便优化,是否有一种方法可以将线性约束放到优化问题本身,这样就可以无拘无束的优化,而不用考虑线性约束了.其对应的拉格朗日对偶形式 ...
- 九款常用的JS代码高亮工具
代码高亮很重要,特别是当我们想要在网站或博客中展示我们的代码的时候.通过在网站或博客中启用代码高亮,读者更方便的读取代码块. 有很多免费而且有用的代码高亮脚本.这些脚本大部分由Javascripts编 ...
- js 控制标记样式
做一个变色的标签 鼠标移入变为灰色,移除变回原来的颜色,点击变成黑色,再点击变回,如果变成黑色不受移入移除影响. <body> <div class="bt1" ...
- Windows系统 安装 Qt 5.7.0
Windows系统 安装 Qt 5.7.0 我们的电脑系统:Windows 10 64位 Qt5 软件:Qt 5. 7. 0 下载 Qt 5.7.0 软件 在这个网站里面,下载:Qt 5.7.0 fo ...