浅谈 关于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中是怎么工作的吗 ...
随机推荐
- mysql 回顾小练习
Student(id,sname,age,sex) 学生表 Course(id,cname,t_id) 课程表 SC(s_id,c_id,score) 成绩表 Teacher(id,Tname) 教师 ...
- 如何将DevExpress的Gridcontrol导出到Excel
private void simpleButton1_Click(object sender, EventArgs e) { SaveFileDialog saveFileDialog = new S ...
- 关于:cross_validation.scores
# -*- coding: utf-8 -*- """ Created on Wed Aug 10 08:10:35 2016 @author: Administrato ...
- chromium浏览器开发系列第二篇:如何编译最新chromium
说一下为什么这么晚才发第二篇,上周和这周department的工作太多了,晚上都是十点半从公司出发,回家以后实在没有多余的精力去摸键盘了.所以请大家包涵! 上期回顾: chromium源码下载: 1. ...
- javascript的概述
JavaScript是怎么诞生的???刚开始的是为了验证表单而开发出来的. 什么是JavaScript???a.面向对象的编程语言b.解释性的编程语言(说白了就是不用编译的一种语言)c.脚本语言(说白 ...
- 算法Sedgewick第四版-第1章基础-1.4 Analysis of Algorithms-003定理
1. 2. 3. 4. 5. 6.
- 算法Sedgewick第四版-第1章基础-024-M/M/1 queue
/****************************************************************************** * Compilation: javac ...
- Linux 查看设置系统语言
一.简介 在Linux的系统中经常碰到字符集导致的错误,本文总结了设置修改系统语言环境的方法步骤. 二.操作步骤 执行如下指令,查看当前使用的系统语言 echo $LANG 执行如下指令,查看系统安装 ...
- 1用java实现冒泡排序算法以及解决的几个小问题。
package huawei.exam; public class BubbleSort { /** * @param args */ public static void main(String[] ...
- Luogu 1979 [NOIP2013] 华容道
要优先安排历年NOIP题 考虑到要移动,肯定要先把空的格子移动到起点旁边,所以我们对于每一个询问都先bfs一次求出把空格移到起点的四个位置的最短路,而且要保证不能移动起点的方块. 只有空的格子在一个格 ...