ios开发基础学习笔记(十三)--autorelease(MRC)

前言

大家好,我是milo,今天这篇文章介绍了MRC下的autorelease,它的作用是能让我们不用再关心对象释放的时间,延长对象的生命周期,让 我们不用再关心什么时候调用release,那么具体要怎么用呢?请接着往下看。

什么时候用?

让我们先看看下面这段代码,从表面上看,创建的对象都对应release了,但是我们忽略了一个问题,就是当我们创建一个myDog指针指向dog指针时,是没有进行retain操作的,而后面的dog进行release操作的时候就已经把对象給释放掉了,所以当我们最后想打印myDog的时候,会报错提示不能向已经销毁的对象发送消息。

int main(int argc, const char * argv[]) {
    JJPerson *person = [[JJPerson alloc] init];
    
    JJDog *dog = [[JJDog alloc] init];
    
    [person setDog:dog];
    
    JJDog *myDog = person.dog;//  这句代码没有进行内存管理

    [dog release];
    
    [person release];
    
    NSLog(@"%zd",[myDog retainCount]);//  这里报错,提示对象已被销毁

    return 0;
}

所以该怎么办呢?我们应该用retain和release操作来完善吗?在后面顺便加一句retain,然后在使用完这个对象后再用release?理论上没问题,但是我们并不能保证我们在写了很多行代码后还能记得去做一个release操作,所以只要一个不小心就会内存泄露或报错。除此之外,我们还会因为太多的retain和release而杂乱。

为了解决这些问题,我们可以使用autorelease。

autoreleasepool(自动释放池)

原理:向一个对象发送autorelease消息,就会把该对象放在自动释放池里,当自动释放池被销毁时,会对池子里的所有对象做一次release操作。

我们将上面的代码做改变,使之没有内存问题。如下:

int main(int argc, const char * argv[]) {
    
    @autoreleasepool {
        
        JJPerson *person = [[JJPerson alloc] init];
        
        JJDog *dog = [[JJDog alloc] init];
        
        [person setDog:dog];
                
        JJDog *myDog = person.dog;
        
        [dog release];
        
        [person release];

        NSLog(@"%zd",[myDog retainCount]);
        
    }

    return 0;
}

由于我们要让myDog指向一个dog,所以可以在JJPerson.m中修改get方法如下:

JJPerson.m

-(JJDog *)dog {    
    [_dog retain];//  让属性对象计数+1
    [_dog autorelease];//  将当前属性对象放入自动释放池
    return _dog;
}

好了,改变做好了,当我们重新运行上述代码的时候,就发现不会报错了,同时也没有内存问题了。

autorelease一般是給除alloc、new、copy、mutableCopy、retain等方式创建出来的对象用的,这样可以方便区分

特点:1、autoreleasepool存储在栈上,可以创建多个,但只有栈顶的池子是活动的,当对象使用[xx autorelease]的时候,会把该对象放在栈顶的池子里 2、调用完autorelease方法后,对象的计数器不变,因为autoreleasepool的功能是在出池子后,所有对象才做release操作

注意:1、autoreleasepool需要配套[xx autorelease]使用,才能在走出池子后,对对象做release操作,不然,也就没有任何意义;你调用几次autorelease,在自动释放池销毁的时候,就会调用几次release 2、某些时候不要随便使用autorelease如占用内存较大的对象或有一个较大的循环的时候,否则会在某一时间段占据太大的内存无法释放。

自动释放池的创建最常见的时@autoreleasepool { 代码段 },就像前面那样;在ios5.0以前是通过 [[NSAutoreleasePool alloc] init] 创建的,当然,现在已经不用这种方式了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,671评论 8 265
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,157评论 1 32
  • OC语言基础 1.类与对象 类方法 OC的类方法只有2种:静态方法和实例方法两种 在OC中,只要方法声明在@int...
    奇异果好补阅读 4,360评论 0 11
  • 内存管理ARC处理原理ARC是Objective-C编译器的特性,而不是运行时特性或者垃圾回收机制,ARC所做的只...
    阳明AI阅读 363评论 0 3
  • 中国有句老话叫做“人前教子,背后教妻”,我们今天就从中国家长推崇“人前教子”的教育理念开始说起。 一直以来,“人前...
    母婴刊阅读 310评论 3 0