苹果如何实现 autorelease

来源:互联网 发布:口型识别的视频数据库 编辑:程序博客网 时间:2024/05/16 07:32

autorelease是苹果引以为傲的地方,它为程序开发人员减轻了很大的开发压力,下面就介绍下autorelease。

autorelease ,顾名思义,就是自动释放,它看上去就像是ARC,其实他更像C语言里面的自动变量(局部变量),

C语言里面的局部变量,就是当变量超出其作用域以后,该自动变量就会被自动抛弃。下面复习下C语言里面的自动变量

-(void)getIt

{

   int a =0;

   /*

     *因为超出变量作用域,

     *自动变量“int a”被废弃,不可再访问

     */

}


audiorelease会像C语言里面对待自动变量那样,对待实例对象,当超出其作用域的时候,对象实例的release方法就会被调用,同自动变量不同的是,对象的作用域可以右程序开发人员自己设定。

autorelease的具体使用方法是:1)、生成并持有NSAutoReseasePool对象。2)、调用已分配对象的autorelease实例方法。3)、废弃NSAutoReseasePool对象

-(void)objcAutorelease

{

    NSAutoreleasePool * autoreleasePool = [[NSAutoreleasePoolalloc]init];

   id objc = [[NSObjectalloc]init];

    [objcautorelease];

    [autoreleasePooldrain];

   /*

     *[autoreleasePool drain] 相当于 [objc release];

     *自动释放池[autoreleasePool drain]的时候,会给池子里面的对象发送一个release消息,让实例变量执行release方法

     */


}


其实需要注意的是,如果大量对象autorelease,只要NSAutoreleasePool没有被废弃,那么生成的对象就不能被释放,就会导致内存不足,典型的例子是读入大量的图片,并且改变图片的尺寸,图像文件读入到NSData对象,并从中生成UIImage对象,这种情况会产生大量的autorelease对象,


for (int i =0; i<10000; i++) {

       /*

         *读入大量图像10000

         *由于没有废弃NSAutoreleasePool对象

         *最终导致内存不足

         */

}


所以可以看出上面的理智是有问题的,所以我们需要在适当的位置,生成、持有、废弃NSAutoreleasePool对象

for (int i =0; i<10000; i++) {

       NSAutoreleasePool * autoreleasePool = [[NSAutoreleasePoolalloc]init];

        

       /*

         *读入大量图像

         *由于没有废弃NSAutoreleasePool对象

         *最终导致内存不足

         */

        [autoreleasePooldrain];

       /*

         *通过[autoreleasePool drain];

         *autorelease对象被一起release

         */   

}


其实在cocoa中,有很多类方法返回autorelease对象,比如说

NSArray * arr1 = [NSArrayarray];//里面已经存在autorelease

NSArray * arr2 = [[[NSArrayalloc]init]autorelease];

    

NSMutableArray * mutableArr1 = [NSMutableArrayarrayWithCapacity:2];

NSMutableArray *mutableArr2 = [[[NSMutableArrayalloc]initWithCapacity:2]autorelease];


arr1 和arr2 mutableArr1和mutableArr1都是一个道理。

其实autorelease的实现,我们可以追溯到源代码

id  obj  = [[NSObjectalloc]init];

[obj autorelease];

其实obj内部实现应该是如下方式

-(void)autorelease

{

    [NSAutoreleasePooladdObject:self];

}

autorelease的实质方法的本质就是调用了NSAutoreleasePool对象的addObject的类方法


那到底苹果自己是如何处理NSAutoreleasePool的呢?它的内部实现应该是怎么样的呢,我们可以简单的如下猜想

NSAutoreleasePool调用的addObject方法如下:


+(void)addObject:(id)anObject

{

    NSAutoreleasePool * autoreleasePool =//取得正在使用NSAutoreleasePool的对象;

   if (autoreleasePool) {

        [autoreleasePool addObject:anObject];

    }else{

        //对象非存在状态下调用autorelease

    }

}

然后是NSAutoreleasePool对象autoreleasePool调用addObject:方法,此时被autorelease的该对象,将会被添加到正在使用的NSAutoreleasePool里面

NSAutoreleasePool的对象能不能autorelease呢?

答案是不能的,如果你调用

[autoreleasePoolautorelease];就会出现异常

控制台你会看到

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSAutoreleasePool autorelease]: Cannot autorelease an autorelease pool'





0 0
原创粉丝点击