iOS---NSAutoreleasePool自动释放原理及详解

当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池 定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。

1.
ojc-c 是通过一种"referring counting"(引用计数)的方式来管理内存的,
对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一,
每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.
2. NSAutoreleasePool 就是用来做引用计数的管理工作的,这个部分后面会详细说到.
3. autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一.

NSAutoreleasePool详解:
1.

NSAutoreleasePool实际上是个对象引用计数自动处理器。NSAutoreleasePool可以同时有多个,它的组织是个栈,总是存在一
个栈顶pool,也就是当前pool,每创建一个pool,就往栈里压一个,改变当前pool为新建的pool,然后,每次给pool发送drain消
息,就弹出栈顶的pool,改当前pool为栈里的下一个 pool。

2. 在程序的入口main函数就调用NSAutoreleasePool,这样保证程序中不调用NSAutoreleasePool,但在退出时自动释放。新开线程最好实现NSAutoreleasePool(当我们点击一个App中的一个按钮或者其他可以触碰开启新业务的UI控件,在程序里面就会自动开启一条新线程,当我们不用这个业务的时候,就需要程序帮我们提前在“程序的主窗口的所有代码编译结束后”之前关闭这条线程以优化线程的使用,一定程度上尽量避免线程开启太多占用CPU严重引起的卡顿问题)(业务逻辑处理-业务线程优化)

3. NSAutoreleasePool的管理范围是在NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];与[pool release];之间的对象

4. NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
当执行[pool autorelease]的时候,系统会进行一次内存释放,把autorelease的对象释放掉,如果没有NSAutoreleasePool , 那这些内存不会释放
注意,对象并不是自动被加入到当前pool中,而是需要对对象发送autorelease消息,这样,对象就被加到当前pool的管理里了。当当前pool接受到drain消息时,它就简单的对它所管理的所有对象发送release消息。
例如

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString* nsstring;
char* cstring = "Hello CString";
nsstring = [NSString stringWithUTF8String:cstring];
[pool release];(这一行代码就是在给pool发送drain消息了)
drain

5. alloc的对象必须显示释放
例如:
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString* string = [[NSString alloc] init];
[string stringByAppendingString:@"Hello World!"];
[pool release];
[nsstring release];///

6如果使用Automatic Reference Counting(ARC).不能直接使用autorelease pools,而是使用@autoreleasepool{},
@autoreleasepool{}比直接使用NSAutoreleasePool效率高。不使用ARC的时候也可以使用(autorelease嵌套:)

7
在引用计数环境中,drain和release一样,但是在garbage-collected环境中,使用drain,触发GC(in a
garbage-collected environment, triggers garbage collection if the memory
allocated since the last collection is greater than the current
threshold)。

8.既然设置了ARC,为什么还要使用@autoreleasepool?

ARC 并不是舍弃了 @autoreleasepool,而是在编译阶段帮你插入必要的 retain/release/autorelease 的代码调用。

所以,跟你想象的不一样,ARC 之下依然是延时释放的,依然是依赖于 NSAutoreleasePool,跟非 ARC 模式下手动调用那些函数本质上毫无差别,只是编译器来做会保证引用计数的正确性。

参考:

官方API摘抄翻译:

autorelease是什么原理?

Autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当 前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。

4、autorelease何时释放?

对于autorelease pool本身,会在如下两个条件发生时候被释放(详细信息请参见第5条)

1)、手动释放Autorelease pool

2)、Runloop结束后自动释放

对于autorelease pool内部的对象在引用计数的retain == 0的时候释放。release和autorelease pool 的 drain都会触发retain--事件。

5、autorelease释放的具体原理是什么?

要搞懂具体原理,则要先要搞清楚autorelease何时会创建。

我们的程序在main()调用的时候会自动调用一个autorelease,然后在每一个
Runloop, 系统会隐式创建一个Autorelease pool,这样所有的release
pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的 Autorelease
pool(main()里的autorelease)会被销毁,这样这个pool里的每个Object会被release。

可以把autorelease
pool理解成一个类似父类与子类的关系,main()创建了父类,每个Runloop自动生成的或者开发者自定义的autorelease
pool都会成为该父类的子类。当父类被释放的时候,没有被释放的子类也会被释放,这样所有子类中的对象也会收到release消息。

那什么是一个Runloop呢? 一个UI事件,Timer call, delegate call, 一个鼠标事件,键盘按下(MAC OSX),或者iphone上的触摸事件,异步http连接下后当接收完数据时,都会是一个新的Runloop。

一般来说,消息循环运行一次是毫秒级甚至微秒级的,因此autorelease的效率仍然是非常高的,确实是一个巧妙的设计。

6、使用有什么要注意的?

1)、NSAutoreleasePool可以创建一个autorelease pool,但该对象本身也需要被释放,如:

  1. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init;
  2. // Code benefitting from a local autorelease pool.
  3. [pool release];

复制代码

在引用计数环境下,使用[pool release]或[pool drain]效果是相同的,drain仅适用于max os高版本,低版本不适用,而release通用,其它并无太大差别。

2)、在ARC下,不能使用上述方式调用autorelease,而应当使用@autoreleasepool,如:

  1. @autoreleasepool {
  2. // Code benefitting from a local autorelease pool.
  3. }

复制代码

3)、尽量避免对大内存使用该方法,如图片。对于这种延迟释放机制,还是尽量少用,最好只用在方法内返回小块内存申请地址值的情况下,且参考和领会OC的一些系统方法,如:[NSString stringWithFormat:]。

4)、不要把大量循环操作放到同一个NSAutoreleasePool之间,这样会造成内存峰值的上升。

7、关于多线程,有什么要注意的?

我还未实际使用到,在官方API翻译出类似如下语句:

1)、对于不同线程,应当创建自己的autorelease pool。如果应用长期存在,应该定期drain和创建新的autorelease pool

下面这句话摘自官方API,大概是说多线程中如果没有使用到cocoa的相关调用,则不需要创建autorelease pool,我一直没有理解透彻

If, however, your detached thread does not make Cocoa calls, you do not need to create an autorelease pool.

2)、如果不是使用的NSThread,就不要用aoturelease pool,除非你是多线程模式(multithreading mode) ,可以使用NSThread的isMultiThreaded方法测试你的应用是否是多线程模式

详细可以参考官方API的NSAutoreleasePool Class Reference

时间: 2024-12-28 12:10:23

iOS---NSAutoreleasePool自动释放原理及详解的相关文章

Foundation框架常用数据类型和NSAutoreleasePool自动释放池解析

第一.NSAutoreleasePool自动释放池解析 1.自动释放池的物理实现 自动释放池用栈来实现,当你创建一个新的自动释放池是,会压栈到栈顶,接受autorelease消息的对象也会被压入到栈顶 NSAutoreleasePool实现延时释放,内部包含一个数组(NSMutableArray),用来保存声名为autorelease的所有对象.如果一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去.NSAutoreleasePool自身在销毁的时候,会遍历一遍

iOS企业证书网页分发全过程详解(图文并茂史无前例的详细哦)

iOS企业证书网页分发全过程详解 苹果的企业级证书发布的应用,是不用设备授权即可直接安装,并且不限设备上限.为了方便分发,苹果有协议实现通过网页链接直接下载安装企业级的应用. 首先需要说明它的原理:基本的原理就是在生成企业证书授权的ipa的同时,要生成一个对应的plist文件,plist文件中会配置ipa的下载地址.版本信息.Bundle ID 等信息,通过网页下载的时候其实下载的是这个plist文件,然后苹果通过自己的协议根据plist文件的配置信息去自动的下载安装app. 这里有个地址用来生

"MindManager"学习iOS系列之"CAAnimation-核心动画"详解,让你的应用“动”起来。

"MindManager"学习iOS系列之"CAAnimation-核心动画"详解,思维导图内展示了CAAnimation-核心动画的大多数基本功能和知识,每个part都有代码讲解,展示出CAAnimation-核心动画的清晰轮廓,编者提供了"JPG"."SWF"."PDF"."Word"."Mmap"格式的源文件供给使用.注意:JPG格式仅为图片总览,SWF格式使用

LVS-DR工作原理图文详解

为了阐述方便,我根据官方原理图另外制作了一幅图,如下图所示:VS/DR的体系结构: 我将结合这幅原理图及具体的实例来讲解一下LVS-DR的原理,包括数据包.数据帧的走向和转换过程. 官方的原理说明:Director接收用户的请求,然后根据负载均衡算法选取一台realserver,将包转发过去,最后由realserver直接回复给用户. 实例场景设备清单: 说明:我这里为了方便,client是与vip同一网段的机器.如果是外部的用户访问,将client替换成gateway即可,因为IP包头是不变的

MapReduce工作原理图文详解 (炼数成金)

MapReduce工作原理图文详解 1.Map-Reduce 工作机制剖析图: 1.首先,第一步,我们先编写好我们的map-reduce程序,然后在一个client 节点里面进行提交.(一般来说可以在Hadoop集群里里面的任意一个节点进行,只要该节点装了Hadoop并且连入了Hadoop集群) 2.job client 在收到这个请求以后呢,会找到JobTracker并且请求一个作业ID(Job ID).(根据我们的核心配置文件,可以很轻易的找到JobTracker) 3.通过HDFS 系统把

IOS开发学习笔记(1)-----UILabel 详解

1. [代码][C/C++]代码     //创建uilabelUILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(20, 40, 280, 80)];//设置背景色label1.backgroundColor = [UIColor grayColor];//设置taglabel1.tag = 91;//设置标签文本label1.text = @"Hello world!";//设置标签文本字体和字体大小label1.

IOS开发学习笔记(2)-----UIButton 详解

1. [代码][C/C++]代码     //这里创建一个圆角矩形的按钮    UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];    //    能够定义的button类型有以下6种,//    typedef enum {//        UIButtonTypeCustom = 0,          自定义风格//        UIButtonTypeRoundedRect,        

ln命令总结,软链接&硬链接&文件删除原理画图详解

ln命令总结,软链接&硬链接&文件删除原理画图详解

从浏览器打开网址到请求到网页内容超细原理过程详解(免费)

从浏览器打开网址到请求到网页内容超细原理过程详解 史上最牛逼相关知识学员讲解! 看完了不服来战! http://edu.51cto.com/course/course_id-6075.html 长江后浪来了...100米高大浪! 最牛逼老男孩教育28期学员开班2个月左右的分享讲解,不看不知道,一看吓尿你! 运维Q群385168604 架构师Q群390642196 PythonQ群29215534大数据Q群421358633