顾名思义,autorelease就是自动释放.这看上去很像ARC,但实际上它更类似于C语言中的自动变量的特性
<pre>
{
int a;
}
因超出变量作用域int a 被废弃,不可访问.
</pre>
autolease
会像C语言的自动变量那样对待对象实例.当超出作用域时,对象实例的release实例方法被调用.autorelease的具体使用方法如下:
<li>生成并持有NSAutoreleasePool对象</li>
<li>调用已分配对象的autolease实例方法</li>
<li>废弃NSAutoreleasePool对象</li>
NSAutoreleasePool对象的生存周期相当于C语言变量的作用域.对于所有掉用过autorelease实例方法的对象,在废弃NSAutoreleasePool对象时,都将调用release方法.源码如下:
<pre>NSAutoreleasePool *pool =[ [NSAutoreleasePool alloc]init]; id obj = [NSObject alloc]init; [obj autolease]; [pool drain]; <==> [obj release];
</pre>
在Cocoa框架中,相当于主程序主循环的NSRunLoop或者在其他程序可运行的地方,对NSAutoreleasePool对象进行生层,持有和废弃处理.因此,应用程序开发者不一定非得使用NSAutoreleasePool对象进行开发工作.
NSRunLoop每次循环中NSAutoreleasePool对象被生成或废弃
<li>生成NSAutoreleasePool对象</li>
<li>应用程序主线程处理操作</li>
<li>废弃NSAutoreleasePool对象</li>
尽管如此,但在大量产生autorelease的对象时,只要不废弃NSAutoreleasePool对象,那么生成的对象就不会被释放,因此会产生内存不足的现象.典型的例子就是读入大量图像的同时改变尺寸
<pre>`
for (int i = 0 i< 图像数; i++)
{
//读入图像
//大量产生autorelease的对象
//由于没有废弃NSAutoreleasePool对象,导致内存不足
}
`</pre>
在此情况下,有必要在适当的地方生成,持有或废弃NSAutoreleasePool对象.
<pre>for (int i = 0 i< 图像数; i++) { //读入图像 //大量产生autorelease的对象 [pool darin]; }
</pre>
另外,Cocoa框架中也有很多类方法用于返回autorelease的对象.比如NSMutableArray类的arrayWithCapactiy类方法.
<pre>id array = [NSMutableArray arrayWithCapactiy:1] =>
id array = [[[NSMutableArray alloc] initWithCapactiy:1] autolease];
</pre>
<ol>总结思考</ol>
<li>NSAutoreleasePool的生命周期问题与RunLoop的关系</li>
<li>类方法内部实现的原理</li>
下面来说说autorelease的实现原理.
以下以GNUstep的源代码为例
<pre>-(id) autorelease { [NSAutoreleasePool addObject:self]; }
</pre>
<pre>+(void) addObject: (id)anObj { NSAutoreleasePool *Pool = 取得正在使用的NSAutoreleasePool对象; if(pool != nil) { [pool addObject:anObj]; }else { NSLog(@"NSAutoreleasePool对象非存在状态下调用NSAutorelease"); } }
</pre>
苹果中的实现
<pre>`
class AutoreleasePoolPage
{
static inline void *push ()
{
相当于生成或持有NSAutoreleasePool类对象;
}
static inline void *pop (void * token)
{
相当于废弃NSAutoreleasePool类对象;
releaseAll( ) ;
}
static inline id autorelease (id obj )
{
相当于NSAutoreleasePool类的addObject类方法
AutoreleasePoolPage *autoreleasePoolPage =取得正在使用的AutoreleasePoolPage实例;
autoreleasePoolPage->add(obj)
}
id *add (id obj)
{
将对象追加到内部数组中;
}
void releaseAll
{
调用内部数组中对象的releasse方法;
}
};
void *objc_autoreleasePoolPush(void)
{
return AutoreleasePoolPage::push ( );
}
void *objc_autoreleasePoolPop(void * ctxt)
{
return AutoreleasePoolPage::pop (ctxt );
}
id *objc_autorelease (id obj)
{
return AutoreleasePoolPage::autorelease (obj );
}
`</pre>
关于具体实现细节,可以查看以下几篇文章
深入理解RunLoop
自动释放池的前世今生
Objective-C Autorelease Pool 的实现原理
网友评论