自动释放池:
(1)在iOS程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的。
(2)当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中
(1)iOS 5.0以前的创建方式
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
`````````````````
[pool release];//[pool drain];用于mac
(2)iOS5.0以后
@autoreleasepool
//开始代表创建自动释放池
·······
}//结束代表销毁自动释放池
autorelease
是一种支持引用计数的内存管理方式
它可以暂时的保存某个对象(object),然后在内存池自己排干(drain)的时候对其中的每个对象
发送release消息
注意,这里只是发送release消息,如果当时的引用计数(reference-counted)依然不为0,则该对象
依然不会被释放。可以用该方法来保存某个对象,也要注意保存之后要释放该对象。
为什么会有autorelease?
OC的内存管理机制中比较重要的一条规律是:谁申请,谁释放。
考虑这种情况,如果一个方法需要返回一个新建的对象,该对象何时释放?
方法内部是不会写release来释放对象的,因为这样做会将对象立即释放而返回一个空对象;调用者也不
会主动释放该对象的,因为调用者遵循“谁申请,谁释放”的原则。那么这个时候,就发生了内存泄露。
这就是不使用autorelease存在的问题
针对这种情况,Objective-C的设计了autorelease,既能确保对象能正确释放,又能返回有效的对象
使用autorelease的好处
(1)不需要再关心对象释放的时间
(2)不需要再关心什么时候调用release
autorelease基本用法
(1)会将对象放到一个自动释放池中
(2)当自动释放池被销毁时,会对池子里的所有对象做一次release
(3)会返回对象本身
(4)调用完autorelease方法后,对象的计数器不受影响(销毁时影响)
(5)我们只需要在自动释放池代码块中调用autorelease 就可以把对象加入到自动释放池
autorelease注意事项:
1. 并不是所有的放到自动释放池中的代码,产生的对象就会自动释放,如果需要释放,必须
加入到自动释放池
int main(int argc, const char * argv[]) {
<span style="white-space:pre"> </span>@autoreleasepool {
<span style="white-space:pre"> </span>//p没有调用autorelease,则没有加入自动释放池
<span style="white-space:pre"> </span>Person *p = [Person new];
<span style="white-space:pre"> </span>}
}
2. 如果对象调用了autorelease 但是,调用autorelease的时候,没有在任何一个自动释放池
中,此时该对象也不会被加入到自动释放池
int main(int argc, const char * argv[]) {
<span style="white-space:pre"> </span>@autoreleasepool {
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>//此时对象在自动释放池外部发送autorealease,不会加入到自动释放池
<span style="white-space:pre"> </span>Person *p = [[Person new] autorelease];
}
3. 不管这个对象是在自动释放池内还是外创建的,只要在自动释放池内写一个[p1 autorelease];
p1就会被放到自动释放池中。注意autorelease是一个方法,且只有在自动释放池中使用才有效。
int main(int argc, const char * argv[]) {
<span style="white-space:pre"> </span>Person *p = [Person new];
<span style="white-space:pre"> </span>@autoreleasepool {
<span style="white-space:pre"> </span>//虽然对象是在自动释放池外部释放的,但只要在内部代用autorealease,即可把对象加入自动释放池
<span style="white-space:pre"> </span>[p autorelease];
<span style="white-space:pre"> </span>}
}
4. autoreleasepool的嵌套:自动释放池,是在栈区创建,以压栈的方式(先进后出),和内存
的栈区是不一样的
int main(int argc, const char * argv[]) {
//第一个创建的自动释放池(最后一个出)
@autoreleasepool {
//第二个创建的自动释放池
@autoreleasepool {
//第三个创建的自动释放池
@autoreleasepool {
//此时的对象处于栈顶,会随着这个自动释放池的释放而释放
[p autorelease]; //此时p被加入到自动释放池
}
}
}
}
4. 自动释放池中不适宜放占用内存比较大的对象
1)尽量避免对大内存使用该方法,对于这种延迟释放机制,还是尽量少用
2)不要把大量循环操作放到同一个 @autoreleasepool 之间,这样会造成内存峰值的上升