黑马程序员—OC基础—autorelease的使用

来源:互联网 发布:中药软件哪个好使 编辑:程序博客网 时间:2024/05/17 01:10


------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
黑马程序员—OC基础—autorelease的使用

自动释放池:

(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 之间,这样会造成内存峰值的上升



0 0