美文网首页IOS开发基础(oc)
ios开发基础学习笔记(十三)--autorelease(MRC

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

作者: miloluo | 来源:发表于2018-06-25 17:46 被阅读0次

    前言

    大家好,我是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] 创建的,当然,现在已经不用这种方式了。

    相关文章

      网友评论

        本文标题:ios开发基础学习笔记(十三)--autorelease(MRC

        本文链接:https://www.haomeiwen.com/subject/twceyftx.html