没有在网上找到好的关于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 深入理解相关推荐

  1. iOS class深入理解: 实例对象、类对象、元类和isa指针

    你要知道的class都在这里 转载请注明出处http://blog.csdn.net/u014205968/ 深入代码理解instance.class object.metaclass 面向对象编程中 ...

  2. iOS - RunLoop 深入理解

    一直不是很了解iOS的runloop机制的具体机制,无意间搜到这个文章,感觉非常详细,收藏了- 作者费不少劲写的,转载请注明出处,谢谢侬.-原文作者:Mitchell 孟晨 于是出处:原文地址 后面我 ...

  3. 48.iOS动画和理解position与anchorPoint

    1.动画的基本概念 动画的使⽤场景:iOS中的动画是指一些视图上的过渡效果,合理利用动画能提⾼用户体验,UIView动画影响的属性 frame:视图框架 center:视图位置 alpha:视图透明度 ...

  4. android iOS 都精通,Android IOS开发要理解何为面向对象的思维

    何为面向对象的思维? 面向对象 VS面向过程 OOP =>面向对象,全称Object Oriented Programming POP =>面向过程,全称Process-oriented ...

  5. iOS多线程简单理解

    1. 何为线程: 一个线程中任务的执行是串行的,同一时间内.一个线程只能执行一个任务. 线程是进程中的一条执行路径 2.何为多线程 一个进程中可以开启多条线程,多条线程可以并行(同时)执行不同的任务 ...

  6. ios arkit原理理解

    一,视频效果 把虚拟的3d椅子放在了真实的世界里. 更多视频: https://www.youtube.com/watch?v=8KmVaW8F9Nc https://www.youtube.com/ ...

  7. 【iOS开发】理解 IBOutlet 和 IBAction

    OUTLET(输出口) 为了能让代码引用nib中的对象,我们在代码中对应的变量前面加上IBOutlet来修饰标记,本身来说它只是个标记,没有什么实际意义,只是用来告诉编译器,这个变量有些特别,是个界面 ...

  8. 【iOS开发】理解Action、IBACtion、Action Connection

    Action Connection(操作) 界面发生事件后,需要一段代码来调用一个方法,响应这个操作,IBAction就是用来标记代码中这个方法的. 在代码中对应的方法前面加上IBAction标记,本 ...

  9. 【iOS开发】理解IBOutlet、Outlet、referencing outlet、outlet connection

    为了能让代码引用nib中的对象,我们在代码中对应的变量前面加上IBOutlet来修饰标记,本身来说它只是个标记,没有什么实际意义,只是用来告诉编译器,这个变量有些特别,是个界面的Outlet,Outl ...

  10. ios软件架构的理解

    http://www.open-open.com/doc/view/afe3090d6d1540c1840bab53b48ba481

最新文章

  1. MySQL sysdate-5_mysql sysdate 1
  2. 第十六届全国大学生智能车竞赛线上赛点赛道审核 - 浙江赛区
  3. c++正则表达式_Python正则表达式教程-常用文本处理技巧
  4. Hibernate之悲观锁与乐观锁
  5. springboot(八):RabbitMQ详解
  6. 怎样提高自己的Java编程能力?
  7. PHP 微信公众号之客服完整讲解
  8. php trait编译实现,为什么PHP Trait不能实现接口?
  9. 如何在EDUIS中导出ETL字幕模板_给视频加字幕?这8个工具助力你的短视频创作!...
  10. 全球信息数据量陡增 大数据应用前景广阔
  11. Decide what you want,and go after it with everything you got!
  12. 金融计量经济学中使用R构建置信区间
  13. 免费注册Gmail邮箱
  14. I Love ces(大小写字母转换 金马五校赛-上海大学)
  15. 内网代理神奇Venom
  16. strcpy s 的用法
  17. 计算机网络_实验16_网络故障导致环路
  18. Cygwin与minGW
  19. java B2B2C源码电子商务平台 ---搭建Eureka注册中心
  20. OpenStack--Glance组件部署!!!

热门文章

  1. Git Bash使用详细教程
  2. 微信小程序 解决disableScroll无法禁止小程序下拉的问题和视频铺满全屏尺寸
  3. Visual Studio Code compile error - launch.json must be configured...
  4. Sublime Text3 插件:convertToUTF8
  5. CentOS设置默认启动命令行(不启动图形界面)
  6. ASP.NET MVC 3.0(十二): MVC 3.0 使用自定义的Html控件
  7. ubuntu 卸载NetworkManager
  8. 用ODBC方式操作dbf文件
  9. Spring.NET学习笔记17——事务传播行为(基础篇) Level 200
  10. HBase的两种协处理器