iOS autoreleasePool 深入理解
没有在网上找到好的关于autoreleasePool的文章,于是打算自己写一篇。从MRC中的自动引用计数开始写,便于理解ARC中的@autoreleasepool。文章地址 参考书籍:《Objective-C 高级编程》
MRC
autorelease是什么
autorelease
会像C语言的自动变量那样来对待实例对象,在超出作用域的时候释放实例对象,不同的是autorelease
可以来手动设定作用域的范围。
autorelease的使用
在MRC中我们通常在一下情况中使用autorelease
:
-(id)object{id = [[NSObject alloc] init];[obj aoturelease]; //这里没有使用NSAutoreleasePool,原因在下面会解释return obj;
}
复制代码
autorelease
:取得对象的存在,但自己不持有对象。
autorelese
提供这样的功能,使对象在超出指定的生存范围时能够自动并正确释放(调用release方法)。 autorelease
将对象注册到autoreleasepool
中,在pool结束(一般是作用域结束的时候),pool自动调用release
autorelease
的具体使用过程:
- 1、生成并持有NSAutoreleasePool对象;
- 2、调用已分配对象的autoreleae实例方法;
- 3、废弃NSAutoreleasePool对象。
示例代码:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //区别于前面的代码这里使用了NSAutoreleasePool
id = obj = [[NSObject alloc] init];
[obj autorelease];
[pool drain]; //在调用这行代码时相当于调用了所有注册到pool中的对象的release方法。复制代码
为什么有时候使用NSAutoreleasePool
有时候不使用NSAutoreleasePool
?
原因:主循环的NSRunLoop会对NSAutoreleasePool进行生成和释放,所以开发者并不是一定得使用NSAutoreleasePool进行开发。也就是说就算你不生成NSAutoreleasePool
,运行时也会自动生成一个。
什么时候使用NSAutoreleasePool对象
虽然NSRunloop会对生成的autorelease对象进行释放,但是短时间内生成的大量对象并不会立即释放,如下:
for(int i = 0 ; ;i++ ){
/**
* 读取图片
* 对图片进行处理
*/
}
//短时间内生成了大量的对象,并不会立即释放,这时候就会造成内存不足,从而引发卡顿。
复制代码
加入NSAutoreleasePool可以解决这个问题:
for(int i = 0 ; ;i++ ){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/**
* 读取图片
* 对图片进行处理
*/
[pool drain];//释放生成的局部变量,就不会造成对象的大量堆积
}
复制代码
autorelease的实现
[obj autorelease];
复制代码
我们来查看一下以上代码在GNUstep中的源代码
GNUstep是cocoa框架的互换框架。也就是说,GNUStep的源代码虽不能说与苹果的Cocoa实现完全相同,但是从使用者的角度来看,两者的行为和实现方式是一样的,或者说非常相似。理解了GNUstep源代码也就相当于理解了苹果的Cocoa实现。
-(id)autorelease
{[NSAutorelease addObject:self];
}
复制代码
autorelease实例方法的本质就是调用了NSAutoreleasePool对象的addObject类方法。 addObject方法的实现(源代码比较复杂,此为简化代码):
+(void)addObject:(id)object{NSAutoreleasePool *pool = 取得正在使用的NSAutoreleasePool对象;if(pool != nil){[pool addObject:object];//pool存在一个array属性来添加所有注册到这个pool中的对象。}else{//error}
}
复制代码
addObject方法中使用的pool对象正是你刚刚生成的NSAutoreleasePool对象,如果嵌套生成NSAutoreleasePool那么获取的pool就是你最内侧的pool对象,也就是“离你的对象最近的NSAutoreleasePool对象”。
[pool drain];
这行代码在运行时会释放所有注册到pool中的对象。 我们来看下drain
方法的实现。
-(void)drain
{[self dealloc];
}
-(void)dealloc
{[self emptyPool];[array release];
}
-(void)emptyPool
{for (id obj in array){[obj release];}
}
复制代码
ARC中autoreleae的使用
ARC有效时我们无法使用autorelease方法,也不能使用NSAutoreleasePool类。但是我们会有书写更方便的替代方法。
使用姿势
ARC无效时:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id = obj = [[NSObject alloc] init];
[obj autorelease];
[pool drain];
复制代码
ARC有效时:
@autoreleasepool{id obj = [[NSObject alloc] init];
}
复制代码
ARC有效时基本不会用到__autoreleasing修饰符,这里就不展开了,有疑问的同学可以留言
@autoreleasepool的实现
当你使用@autoreleasepool的时候,编译器会有一份替换代码。 你的代码:
@autoreleasepool{id obj = [[NSObject alloc] init];
}
复制代码
编译器的模拟代码:
id pool = objc_autoreleasePoolPush();
id = objc_msgSend(NSObject,@selector(alloc));
objc_msgSend(obj,@selector(init));
objc_autorelease(obj);
objc_autoreleasePoolPop(pool);
复制代码
我们可以看到编译器转换后的代码和我们前面的NSAutoreleasePool类的使用方式一模一样,所以不管ARC是否有效autorelease的功能一模一样。
转载于:https://juejin.im/post/5c90bbd0f265da60d36e6c39
iOS autoreleasePool 深入理解相关推荐
- iOS class深入理解: 实例对象、类对象、元类和isa指针
你要知道的class都在这里 转载请注明出处http://blog.csdn.net/u014205968/ 深入代码理解instance.class object.metaclass 面向对象编程中 ...
- iOS - RunLoop 深入理解
一直不是很了解iOS的runloop机制的具体机制,无意间搜到这个文章,感觉非常详细,收藏了- 作者费不少劲写的,转载请注明出处,谢谢侬.-原文作者:Mitchell 孟晨 于是出处:原文地址 后面我 ...
- 48.iOS动画和理解position与anchorPoint
1.动画的基本概念 动画的使⽤场景:iOS中的动画是指一些视图上的过渡效果,合理利用动画能提⾼用户体验,UIView动画影响的属性 frame:视图框架 center:视图位置 alpha:视图透明度 ...
- android iOS 都精通,Android IOS开发要理解何为面向对象的思维
何为面向对象的思维? 面向对象 VS面向过程 OOP =>面向对象,全称Object Oriented Programming POP =>面向过程,全称Process-oriented ...
- iOS多线程简单理解
1. 何为线程: 一个线程中任务的执行是串行的,同一时间内.一个线程只能执行一个任务. 线程是进程中的一条执行路径 2.何为多线程 一个进程中可以开启多条线程,多条线程可以并行(同时)执行不同的任务 ...
- ios arkit原理理解
一,视频效果 把虚拟的3d椅子放在了真实的世界里. 更多视频: https://www.youtube.com/watch?v=8KmVaW8F9Nc https://www.youtube.com/ ...
- 【iOS开发】理解 IBOutlet 和 IBAction
OUTLET(输出口) 为了能让代码引用nib中的对象,我们在代码中对应的变量前面加上IBOutlet来修饰标记,本身来说它只是个标记,没有什么实际意义,只是用来告诉编译器,这个变量有些特别,是个界面 ...
- 【iOS开发】理解Action、IBACtion、Action Connection
Action Connection(操作) 界面发生事件后,需要一段代码来调用一个方法,响应这个操作,IBAction就是用来标记代码中这个方法的. 在代码中对应的方法前面加上IBAction标记,本 ...
- 【iOS开发】理解IBOutlet、Outlet、referencing outlet、outlet connection
为了能让代码引用nib中的对象,我们在代码中对应的变量前面加上IBOutlet来修饰标记,本身来说它只是个标记,没有什么实际意义,只是用来告诉编译器,这个变量有些特别,是个界面的Outlet,Outl ...
- ios软件架构的理解
http://www.open-open.com/doc/view/afe3090d6d1540c1840bab53b48ba481
最新文章
- MySQL sysdate-5_mysql sysdate 1
- 第十六届全国大学生智能车竞赛线上赛点赛道审核 - 浙江赛区
- c++正则表达式_Python正则表达式教程-常用文本处理技巧
- Hibernate之悲观锁与乐观锁
- springboot(八):RabbitMQ详解
- 怎样提高自己的Java编程能力?
- PHP 微信公众号之客服完整讲解
- php trait编译实现,为什么PHP Trait不能实现接口?
- 如何在EDUIS中导出ETL字幕模板_给视频加字幕?这8个工具助力你的短视频创作!...
- 全球信息数据量陡增 大数据应用前景广阔
- Decide what you want,and go after it with everything you got!
- 金融计量经济学中使用R构建置信区间
- 免费注册Gmail邮箱
- I Love ces(大小写字母转换 金马五校赛-上海大学)
- 内网代理神奇Venom
- strcpy s 的用法
- 计算机网络_实验16_网络故障导致环路
- Cygwin与minGW
- java B2B2C源码电子商务平台 ---搭建Eureka注册中心
- OpenStack--Glance组件部署!!!
热门文章
- Git Bash使用详细教程
- 微信小程序 解决disableScroll无法禁止小程序下拉的问题和视频铺满全屏尺寸
- Visual Studio Code compile error - launch.json must be configured...
- Sublime Text3 插件:convertToUTF8
- CentOS设置默认启动命令行(不启动图形界面)
- ASP.NET MVC 3.0(十二): MVC 3.0 使用自定义的Html控件
- ubuntu 卸载NetworkManager
- 用ODBC方式操作dbf文件
- Spring.NET学习笔记17——事务传播行为(基础篇) Level 200
- HBase的两种协处理器