解决的问题

每一个东西的产生都是在实际生活迫切需要这样的东西后,人们通过思考发明创造某些东西用以解决这个问题。那么自动释放池用来解决什么问题?请看下面的例子:

对于一些有返回值的消息(方法),它返回的对象要交给谁来释放其内存,比如NSObject类中description消息

-(NSString*)description{NSString *description;description = [[NSString alloc]initWithFormat:@"hello world"];return (description);}//description

这个时候description字符串的内存释放要交给谁?肯定不应该在description方法里面,这样的话,返回的对象指向的就是一个被释放的内存了。这肯定是不可行的。

那么如果让调用者来释放呢,那么就得像下面这样写:

RetainTracker *tracker = [RetainTracker new];NSString *desc = [tracker description];[desc release];

那么这样写有什么问题么?没什么问题,就是多了一行代码?有什么更好的方法,能只写一行代码就能达到自动释放的效果。既然有这个需求,那么肯定会有人试着去解决这个问题。

解决方法

苹果公司在Cocoa框架中有一个自动释放池的概念,在NSObject类中提供了一个叫做autorelease的方法。

-(id)autorelease{};//autorelease

该方法预先设定了一条会在未来某个时间发送的release消息, 返回的id代表接受这条消息的对象。当我们调用该对象的autorelease方法的时候,实际上是把该对象放到自动释放池,当自动释放池被销毁时,会向该池中的所有对象发送release消息。这个时候我们把description 方法修改成如下形式:

-(NSString*)description
{NSString *description;description = [[NSString alloc]initWithFormat:@"hello world"];return ([description autorelease]);}//description

这个时候我们在调用的地方只需要一句话就做了内存释放的工作。不用在单独添加调用release方法的语句。

创建

我们上面说了那么多,都在说自动释放池可以帮我们解决掉对象自动释放的问题,但是这个自动释放池也不是自己就存在的,它需要我们自己来显示的创建。可以通过2种方式来创建自动释放池。

通过@autoreleasepool关键字

当你使用@autoreleasepool{}时,所有在花括号里的代码都会被放入这个池子中。但是任何在该花括号的变量都无法在括号外使用。

通过NSAutoreleasePool对象

该对象需要创建,在该对象创建语句和销毁语句的代码都相当于放入了自动释放池中。

NSAutoreleasePool *pool;pool = [NSAutoreleasePool new];RetainTracker *tracker = [RetainTracker new];NSString *desc = [tracker description];[desc release];// count: 1[tracker retain]; // count: 2NSLog (@"%d", [tracker retainCount]);[tracker retain]; // count: 3NSLog (@"%d", [tracker retainCount]);[tracker release]; // count: 2NSLog (@"%d", [tracker retainCount]);[tracker release]; // count: 1NSLog (@"%d", [tracker retainCount]);[tracker retain]; // count 2NSLog (@"%d", [tracker retainCount]);[tracker release]; // count 1NSLog (@"%d", [tracker retainCount]);[tracker release]; // count: 0, dealloc it[pool release];

上面的代码就是一个自动释放池创建过程。

推荐

优先使用@autoreleasepool{}关键字的方式来创建自动释放池。

工作原理

那么自动释放池的工作原理到底是什么?下面用一个例子来讲解一下。

#import <Foundation/Foundation.h>@interface RetainTracker : NSObject
@end // RetainTracker@implementation RetainTracker- (id) init
{if (self = [super init]) {NSLog (@"init: Retain count of %d.",[self retainCount]);}return (self);} // init- (void) dealloc
{NSLog (@"dealloc called. Bye Bye.");[super dealloc];} // dealloc@end // RetainTrackerint main (int argc, const char * argv[])
{NSAutoreleasePool *pool;pool = [[NSAutoreleasePool alloc] init];RetainTracker *tracker;tracker = [RetainTracker new]; // count: 1[tracker retain]; // count: 2[tracker autorelease]; // count: still 2[tracker release]; // count: 1NSLog (@"releasing pool");[pool release]; // gets nuked, sends release to tracker@autoreleasepool{RetainTracker *tracker2;tracker2 = [RetainTracker new]; // count: 1[tracker2 retain]; // count: 2[tracker2 autorelease]; // count: still 2[tracker2 release]; // count: 1NSLog (@"auto releasing pool");}return (0);
}

第一个代码块是使用NSAutoreleasePool对象创建的自动释放池。和之前的语句相比,多了一个[tracker autorelease]语句,该语句做了啥?它并没有给引用计数器的值做操作,而是把该对象添加到自动释放池中,在自动释放池中也有一个引用指向了该对象。当自动释放池销毁时,会向改对象发送一条release消息。由于我们先向tracker对象发送了retain对象,计数器加1,然后发送release消息,计数器减1,但是此时tracker对象的dealloc方法并不会调用,因为new方法让计数器加1,所以pool对象的release方法没调用之前,tracker对象的计数器的值为1,当pool对象的调用release后,自动释放池的计数器为0,此时pool对象的dealloc方法会被调用,然后会想池中的对象发送release对象,那么此时tracker对象的计数器值会变为0,tracker对象的dealloc方法被调用,所以输出应该如下:

2015-02-01 00:12:02.426 09.02 RetainCount-2[860:58571] init: Retain count of 1.
2015-02-01 00:12:02.428 09.02 RetainCount-2[860:58571] releasing pool
2015-02-01 00:12:02.428 09.02 RetainCount-2[860:58571] dealloc called. Bye Bye.

另外一个@autoreleasepool关键字创建的自动释放池也是一样的过程。整个输出如下:

2015-02-01 00:18:23.932 09.02 RetainCount-2[876:61410] init: Retain count of 1.
2015-02-01 00:18:23.933 09.02 RetainCount-2[876:61410] releasing pool
2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] dealloc called. Bye Bye.
2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] init: Retain count of 1.
2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] auto releasing pool
2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] dealloc called. Bye Bye.
Program ended with exit code: 0

Objective-c自学笔记(5)-自动释放池相关推荐

  1. [Objective-C] 自动释放池(Autoreleasepool)--拆迁队的外援

    C#妹妹:内存的清理跟生活中的拆迁一样是个麻烦事情啊 Objective-C阿姨:是啊,该拆的不拆,占用空间,不该拆的拆了,程序崩溃 C#妹妹:说白了,难度不在拆上,在判定上,判断到底那些内存是用不上 ...

  2. 《C#妹妹和Objective-C阿姨对话录》(05)自动释放池--拆迁队的外援

    C#妹妹:内存的清理跟生活中的拆迁一样是个麻烦事情啊 Objective-C阿姨:是啊,该拆的不拆,占用空间,不该拆的拆了,程序崩溃 C#妹妹:说白了,难度不在拆上,在判定上,判断到底那些内存是用不上 ...

  3. ios中的自动释放池

    自动释放池中是否有虑重功能 1 @autoreleasepool { 2 UIView *view = [UIView alloc] init] autorelease]; 3 [view autor ...

  4. iOS 多线程 自动释放池常见面试题代码

    同步:代码依次执行,一个人执行多个任务,也是依次执行.一个人在同一时间只执行一个任务 异步:可以同时执行多个任务 进程:指在系统中运行的应用程序,每个进程都是独立的,都有独立的且安全的运行空间 线程: ...

  5. 内存管理-定时器循环、内存布局、tagged pointer、weak指针、copy、自动释放池

    先上代码,我们平时用的定时器,cadisplaylink.nstimer,CADisplayLink.NSTimer会对target产生强引用,如果target又对它们产生强引用,那么就会引发循环引用 ...

  6. 自动释放池autoreleasepool

    自动释放池是NSAutoreleasePool的实例,其中包含了收到autorelease消息的对象.当一个自动释放池自身被销毁(dealloc)时,它会给池中每一个对象发送一个release消息(如 ...

  7. 【深入Cocos2d-x】探索Cocos2d-x中的内存管理-引用计数和自动释放池

    2019独角兽企业重金招聘Python工程师标准>>> #深入Cocos2d-x-探索Cocos2d-x中的内存管理-引用计数和自动释放池 ###引用计数(Reference Cou ...

  8. 第六讲:Obj-C 内存管理4 - 自动释放池

    转:http://tigercat1977.blog.163.com/blog/static/2141561122012111294616203/ 第六讲:Obj-C 内存管理4 - 自动释放池 主要 ...

  9. iOS之深入解析自动释放池autoreleasepool的底层原理

    一.自动释放池 autoreleasepool 原理 自动释放池是 OC 中的一种内存自动回收机制,它可以将加入 autoreleasePool 中的变量 release 的时机延迟. 简单来说,就是 ...

最新文章

  1. 机器学习笔记:线性规划,梯度下降
  2. 在VS2010中使用wxWidgets 2.9.3
  3. golang实现图片上传和下载
  4. Python 之 使用 PIL 库做图像处理
  5. QTP的那些事--共享对象库的使用
  6. 门面模式(Facade)
  7. 经济学python值得学吗_地藏经注音,地藏经全文,地藏经全文(注音版)——学佛网...
  8. linux下安装tuxedo
  9. photoshop图片放大不失真
  10. AWD简单介绍和搭建AWD平台
  11. QT installs的使用,编译时拷贝文件
  12. 计算机windows7桌面是指什么,在windows7中,桌面指的是什么
  13. windows环境系安装flask框架,pyth3.x版本
  14. 魔术轮胎,dugoff轮胎建模 采用模块化建模方法,搭建非线性魔术轮胎PAC2002,dugoff模型
  15. 考研最卷的专业,我提名新传
  16. `全网最细!! 入门必看Git教程链接:https://gitee.com/all-about-git`
  17. 用python的turtle模块给女票画个小心心
  18. Google 收购摩托罗拉移动将会对全球手机市场格局带来哪些深远影响?
  19. 邮件基本常识普及(to/cc/bcc)
  20. 如何将 SWF 文件添加到 PPT 的每一张幻灯片

热门文章

  1. ftp服务器连接数修改,ftp服务器连接数设置
  2. JavaFXGL框架笔记
  3. springboot项目Banner配置
  4. 【MATLAB】求复合函数
  5. PaddlePaddle - 人脸关键点检测课程笔记
  6. Python实现电报加密(字母后移一位)
  7. 微信小程序OTO商城(客户端)
  8. ECharts之类型3D(map,bar3D,scatter3D)
  9. iframe框架内嵌vue项目:Blocked a frame with origin http://xxxx from accessing a cross-origin iframe.解决办法
  10. INFOR SCE开发说明