自动释放池

2019-01-13  本文已影响4人  高思阳

MRC想要将对象放进autoreleasepool中,必须显示调用autorelease

自动释放池Autoreleasepool

自动释放池是Object-C提供的一种对象自动进行释放的机制。它的基本思想是把需要进行释放的对象都放到一个空间存储起来,找个时机对这些对象一起发送release消息,相当于对对象的一个延时释放的过程。autoreleasepool就是负责储存需要release的对象的,等到autoreleasepool被销毁的时候(通常都是运行到大括号结束),对池内所有对象发送一遍release消息。

//创建自动释放池


@autoreleasepool

{

} 

在程序运行中,并不是把对象放到autoreleasepool里面就可以被自动释放,还需要调用该对象的autorelease方法才行,对象可以不在autoreleasepool里面创建,但是一定要在autoreleasepool里面调用autorelease方法,才能达到释放的目的。


HITStudent *stu = [[HITStuent alloc]init];

HITStudent *stu1 = [[HITStuent alloc]init];

HITStudent *stu2 = [[HITStuent alloc]init];

[stu2 retain];

@autoreleasepool

{

    HITStudent *stu3 =[[[HITStuent alloc] init] autorelease];

    [stu1 autorelease];

    [stu2 autorelease];

    [stu2 autorelease];  //stu2有一个retain操作,需要autorelease两次

}

上面代码中stu没有调用autorelease不能进行自动释放,stu1,stu2,stu3都能正常的进行自动释放。autorelease相当于一个延时的release,所以只要保证retain/alloc的总数与autorelease相等即可。

如果新建一个Single View Application工程,我们会发现在main()函数开始的时候就会生成一个自动释放池,,这样做并没有什么实际意义,因为就算不释放这些对象,程序结束后系统也会回收。真正使用autoreleasepool的场景是把大量使用临时变量的代码段或者需要长时间运行的代码段放到autoreleasepool中,从而提高内存使用率。

注:用某个方法生成对象,并将其作为方法的返回值,这时我们该如何处理

1) 通过alloc new copy mutableCopy 或其他符合命名规则的方法生成的对象,只需要原封不动的返回就能让调用方也持有该对象


- (id)allocObject {

    id obj = [[NSObject alloc] init];

    return obj;

}

- (id)allocObjectWithObject:(id)obj {

    id object = [obj allocObject];

    return object;

}      

2) 如果持有非自己生成的对象,例如[NSMutableArray array]生成的对象,我们要使用autorelease方法释放

注:命名规则:用来取得谁都不持有的对象的方法名不能以alloc new copy mutableCopy开头


- (id)object {  

    id obj = [NSMutableArray array];

    [obj autorelease];

    return obj;

}

因为:autorelease方法:提供了这样的功能,使对象在超出指定的生存范围时自动并正确释放(调用release方法)

release和autorelease区别

自动释放池的应用场景

MRC:

1、对象作为函数返回值

当一个对象要作为函数返回值的时候,因为要遵循谁申请谁释放的思想,所以应该在返回之前释放,但要是返回之前释放了,就会造成野指针错误,但是要是不释放,那么就违背了谁申请谁释放的原则,所以就可以使用autorelease延迟释放的特性,将其在返回之前做一次autorelease,加入到自动释放池中,保证可以被返回,一次runloop之>>后系统会帮我们释放他

2、临时生成大量对象,一定要将自动释放池放在for循环里面,要释放在外面,就会因为大量对象得不到及时释放,而造成内存紧张,最后程序意外退出


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

        @autoreleasepool {

            UIImageView *imegeV = [[UIImageView alloc]init];

            imegeV.image = [UIImage imageNamed:@"efef"];

            [self.view addSubview:imegeV];

        }

    }

上一篇下一篇

猜你喜欢

热点阅读