您的位置:首页 > 编程语言 > C语言/C++

黑马程序员——OC语言加强---autorelease基本使用

2015-10-06 18:19 495 查看
                                                                ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!
-------

autorelease基本使用
1、自动释放池及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,则该对象依然不会被释放。可以用该方法来保存某个对象,也要注意保存之后要释放该对象。
2、为什么会有autorelease?

OC的内存管理机制中比较重要的一条规律是:谁申请,谁释放。
考虑这种情况,如果一个方法需要返回一个新建的对象,该对象何时释放?
方法内部是不会写release来释放对象的,因为这样做会将对象立即释放而返回一个空对象;调用者也不会主动释放该对象的,因为调用者遵循“谁申请,谁释放”的原则。那么这个时候,就发生了内存泄露。
这就是不使用autorelease存在的问题
针对这种情况,Objective-C的设计了autorelease,既能确保对象能正确释放,又能返回有效的对象
使用autorelease的好处
(1)不需要再关心对象释放的时间
(2)不需要再关心什么时候调用release
3、autorelease基本用法
基本用法

(1)会将对象放到一个自动释放池中
(2)当自动释放池被销毁时,会对池子里的所有对象做一次release
(3)会返回对象本身
(4)调用完autorelease方法后,对象的计数器不受影响(销毁时影响)
在autorelease的模式下,下述方法是合理的,即可以正确返回结果,也不会造成内存泄露
ClassA*Func1()
{
   ClassA *obj = [[[ClassA alloc]init]autorelease];
   return obj;
}  
4、autorelease是什么原理?

    autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放
b102
入了当前的Autoreleasepool中,当该pool被释放时,该pool中的所有Object会被调用
Release。
5、autorelease何时释放?
   
对于autoreleasepool本身,会在如下两个条件发生时候被释放(详细信息请参见第5条)

1)手动释放Autoreleasepool
2)Runloop结束后自动释放
对于autoreleasepool内部的对象

在引用计数的retain ==0的时候释放。release和autorelease pool 的 drain都会触发retain-- 事件。
6、autorelease释放的具体原理是什么?

要搞懂具体原理,则要先搞清楚autorelease何时会创建。
我们的程序在main()调用的时候会自动调用一个autorelease,然后在每一个Runloop,系统会隐式创建一个Autorelease pool,这样所有的releasepool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的 Autoreleasepool(main()里的autorelease)会被销毁,这样这个pool里的每个Object会被release。
可以把autoreleasepool理解成一个类似父类与子类的关系,main()创建了父类,每个Runloop自动生成的或者开发者自定义的autoreleasepool都会成为该父类的子类。当父类被释放的时候, 没有被释放的子类也会被释放,这样所有子类中的对象也会收到release消息。那什么是一个Runloop呢?
一个UI事件,Timer call, delegate call, 一个鼠标事件,键盘按 下(MACOSX),或者iphone上的触摸事件,异步http连接下后当接收完数据时,都会是一个新的 Runloop。一般来说,消息循环运行一次是毫秒级甚至微秒级的,因此autorelease的效率仍然是非常高的, 确实是一个巧妙的设计。 
对象调用autorelease方法,自己的引用计数并没有减一,它只是将对象放到了一个池子中。池子销毁时,只会对它里面的对象做一次release操作。
池子也是以压栈的方式在内存中存储的。 
苹果官方提供的方法(API)
1,如果方法名不是alloc,new,就不用release或者autorelease;
2,如果方法名是alloc,new,就必须release或者autorelease。
<span style="font-size:14px;">#import <Foundation/Foundation.h>
@interface Person : NSObject
-(void)run;
@end
@implementation Person
- (void)dealloc
{
NSLog(@"Person dealloc");
[super dealloc];
}
-(void)run{
NSLog(@"人在跑");
}
@end
int main(int argc, const char * argv[]) {
//1 创建自动释放池
Person *p = [Person new];  // p  1
@autoreleasepool {//自动释放池开始
[p run];
NSLog(@"%lu",p.retainCount); // 1
// [p autorelease] 把对象p加入到自动释放池中
// 注意:加入到自动释放池中以后, 引用计数不会变化
[p autorelease];  //加入自动释放池,
NSLog(@"%lu",p.retainCount); // 1
[p run];
}//自动释放池结束   [p release];
[p run];
return 0;
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息