A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

1、自动释放池及autorelease介绍
自动释放池
(1)在iOS程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的。
(2)当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中
(1)iOS 5.0以前的创建方式
        NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];       
        `````````````````
        [pool release];//[pool drain];用于mac
(2)iOS5.0以后
        @autoreleasepool
        {//开始代表创建自动释放池
            ·······            
        }//结束代表销毁自动释放池       
autorelease
是一种支持引用计数的内存管理方式
它可以暂时的保存某个对象(object),然后在内存池自己的排干(drain)的时候对其中的每个对象发送release消息
注意,这里只是发送release消息,如果当时的引用计数(reference-counted)依然不为0,则该 对象依然不会被释放。可以用该方法来保存某个对象,也要注意保存之后要释放该对象。
2、为什么会有autorelease?
OC的内存管理机制中比较重要的一条规律是:谁申请,谁释放。
考虑这种情况,如果一个方法需要返回一个新建的对象,该对象何时释放?
方法内部是不会写release来释放对象的,因为这样做会将对象立即释放而返回一个空对象;调用者也不会主动释放该对象的,因为调用者遵循“谁申请,谁释放”的原则。那么这个时候,就发生了内存泄露。
这就是不使用autorelease存在的问题
针对这种情况,Objective-C的设计了autorelease,既能确保对象能正确释放,又能返回有效的对象
使用autorelease的好处
        (1)不需要再关心对象释放的时间
        (2)不需要再关心什么时候调用release
3、autorelease基本用法
基本用法
        (1)会将对象放到一个自动释放池中
        (2)当自动释放池被销毁时,会对池子里的所有对象做一次release
        (3)会返回对象本身
        (4)调用完autorelease方法后,对象的计数器不受影响(销毁时影响)
在autorelease的模式下,下述方法是合理的,即可以正确返回结果,也不会造成内存泄露
        ClassA *Func1()
        {
            ClassA *obj = [[[ClassA alloc]init]autorelease];
            return obj;
        } 
3、autorelease是什么原理?
         autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用 Release。
4、autorelease何时释放?
    对于autorelease pool本身,会在如下两个条件发生时候被释放(详细信息请参见第5条)
        1)手动释放Autorelease pool
        2)Runloop结束后自动释放
对于autorelease pool内部的对象
在引用计数的retain == 0的时候释放。release和autorelease pool 的 drain都会触发retain-- 事件。
5、autorelease释放的具体原理是什么?
       要搞懂具体原理,则要先搞清楚autorelease何时会创建。
我们的程序在main()调用的时候会自动调用一个autorelease,然后在每一个Runloop, 系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的 Autorelease pool(main()里的autorelease)会被销毁,这样这个pool里的每个Object会被release。
可以把autorelease pool理解成一个类似父类与子类的关系,main()创建了父类,每个Runloop自动生成的或者开发者自定义的autorelease pool都会成为该父类的子类。当父类被释放的时候, 没有被释放的子类也会被释放,这样所有子类中的对象也会收到release消息。 那什么是一个Runloop呢? 一个UI事件,Timer call, delegate call, 一个鼠标事件,键盘按 下(MAC OSX),或者iphone上的触摸事件,异步http连接下后当接收完数据时,都会是一个新的 Runloop。 一般来说,消息循环运行一次是毫秒级甚至微秒级的,因此autorelease的效率仍然是非常高的, 确实是一个巧妙的设计。
对象调用autorelease方法,自己的引用计数并没有减一,它只是将对象放到了一个池子中。池子销毁时,只会对它里面的对象做一次release操作。
池子也是以压栈的方式在内存中存储的。
苹果官方提供的方法(API)
1,如果方法名不是alloc,new,就不用release或者autorelease;
2,如果方法名是alloc,new,就必须release或者autorelease。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马