美文网首页面试题
一个autorealese对象在什么时刻释放?

一个autorealese对象在什么时刻释放?

作者: 暗夜精灵_NightElf | 来源:发表于2017-12-01 11:28 被阅读0次

    不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)

    分两种情况:手动干预释放时机、系统自动去释放。

    1.手动干预释放时机--指定autoreleasepool 就是所谓的:当前作用域大括号结束时释放。

    系统自动去释放--不手动指定autoreleasepool

    2.Autorelease对象出了作用域之后,会被添加到最近一次创建的自动释放池中,并会在当前的 runloop 迭代结束时释放。

    释放的时机总结起来,可以用下图来表示:

    autoreleasepool.png

    下面对这张图进行详细的解释:

    从程序启动到加载完成是一个完整的运行循环,然后会停下来,等待用户交互,用户的每一次交互都会启动一次运行循环,来处理用户所有的点击事件、触摸事件。

    我们都是知道:所有 autorelease 的对象,在出了作用域之后,会被自动添加到最近创建的自动释放池中。

    但是如果每次都放进应用程序的 main.m

    中的 autoreleasepool 中,迟早有被撑满的一刻。这个过程中必定有一个释放的动作。何时?

    在一次完整的运行循环结束之前,会被销毁。

    那什么时间会创建自动释放池?运行循环检测到事件并启动后,就会创建自动释放池。

    子线程的 runloop 默认是不工作,无法主动创建,必须手动创建。

    自定义的 NSOperation 和 NSThread 需要手动创建自动释放池。比如: 自定义的 NSOperation 类中的 main 方法里就必须添加自动释放池。否则出了作用域后,自动释放对象会因为没有自动释放池去处理它,而造成内存泄露。

    但对于 blockOperation 和 invocationOperation 这种默认的Operation ,系统已经帮我们封装好了,不需要手动创建自动释放池。

    @autoreleasepool 当自动释放池被销毁或者耗尽时,会向自动释放池中的所有对象发送 release 消息,释放自动释放池中的所有对象。

    如果在一个vc的viewDidLoad中创建一个 Autorelease对象,那么该对象会在 viewDidAppear 方法执行前就被销毁了。

    参考链接:《黑幕背后的Autorelease》

    这个问题拿来做面试题,问过很多人,没有几个能答对的。很多答案都是“当前作用域大括号结束时释放”,显然木有正确理解Autorelease机制。在没有手加Autorelease Pool的情况下,Autorelease对象是在当前的runloop

    迭代结束时释放的,而它能够释放的原因是系统在每个runloop迭代中都加入了自动释放池Push和Pop

    __weak id reference = nil;

    - (void)viewDidLoad {

    [super viewDidLoad];

    NSString *str = [NSString stringWithFormat:@"sunnyxx"];

    // str是一个autorelease对象,设置一个weak的引用来观察它

    reference = str;

    }

    - (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    NSLog(@"%@", reference); // Console: sunnyxx

    }

    - (void)viewDidAppear:(BOOL)animated {

    [super viewDidAppear:animated];

    NSLog(@"%@", reference); // Console: (null)

    }

    由于这个vc在loadView之后便add到了window层级上,所以viewDidLoad和viewWillAppear是在同一个runloop调用的,因此在viewWillAppear中,这个autorelease的变量依然有值。

    当然,我们也可以手动干预Autorelease对象的释放时机:

    - (void)viewDidLoad{

    [super viewDidLoad];

    @autoreleasepool {

    NSString *str = [NSString stringWithFormat:@"sunnyxx"];

    }

    NSLog(@"%@", str); // Console: (null)

    }

    作者:TEASON

    链接:http://www.jianshu.com/p/1ddd0603d7e1

    來源:简书

    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    相关文章

      网友评论

        本文标题:一个autorealese对象在什么时刻释放?

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