ARC下AutoReleasePool的误区

开发者 2024-9-20 16:43:01 42 0 来自 中国
写这边文章的缘故原由是看到网络上对于AutoReleasePool讨论,发现各人对AutoReleasePool存在误区。
AutoReleasePool 内里的对象何时开释?
这个标题是常见的iOS口试题,错误的答案:
1.比及一次runloop竣事,AutoReleasePool被开释时
2.超出作用域{}
这些答案都不对,尺度答案:
每次release时retainCount减一,当retainCount为0时间开释对象。release的机会比如runloop周期中AutoReleasePool被开释时,比如超出作用域时
关键概念点:
1. 不是全部OC对象都会参加到AutoReleasePool
2. AutoReleasePool被开释时内里的对象不肯定会开释,超出作用域一样不肯定会开释

  • 不是全部OC对象都会参加到AutoReleasePool
    AutoReleasePool是ARC的一部分,本质上照旧RC的机制,一个对象在ARC下,大概会被参加到autoreleasepool内里,也大概不会。比如被__autoreleasing标记大概@autoreleasepool包裹的大概UIImage对象都会参加AutoReleasePool,其他的像只是单纯创建NSObject是不会,但是调用了NSObject的对象方法后是会参加AutoReleasePool的。

  • AutoReleasePool被开释时内里的对象不肯定会开释,超出作用域同样的道理
    AutoReleasePool被开释时内里的对象大概另有其他引用,以是AutoReleasePool被开释时内里的对象只会实行release操纵,并不肯定会开释对象。
正常环境:

    __weak id objA = nil;    {        id objB = [NSObject new];        objA = objB;    }    NSLog(@"%@", objA);    // objA = null这个是没有异议的环境,objB出了作用域就会被开释,但是下面的代码就不一样了
AutoReleasePool被开释时有其他引用:

    id objA = nil;    @autoreleasepool {        id objB = [NSObject new];        objA = objB;    }    NSLog(@"%@", objA);    // objA = <NSObject: 0x600002708330>objB固然被参加到主动开释池,但是并不会被开释掉,由于另有objA在强引用它。如果这里的objA是weak的,objB会被开释
出了作用域但是AutoReleasePool没有开释:

    __weak id objA = nil;    {        __autoreleasing id objB = [NSObject new];        objA = objB;    }    NSLog(@"%@", objA);    // objA = <NSObject: 0x600000c545c0>objA固然是弱引用,但是__autoreleasing的AutoReleasePool是和objA同级的,要等AutoReleasePool开释的时间objB才会被开释,纵然objB已经出了作用域,实在这里出作用域的时间并没有实行release操纵
AutoReleasePool开释了,同时出了作用域,就会被开释:

    __weak id objA = nil;    {        id objB = nil;        @autoreleasepool {            __autoreleasing NSObject *objC = [NSObject new];            objB = objC;        }        objA = objB;        NSLog(@"objA = %@", objA);        //objA = <NSObject: 0x60000188c0c0>    }    NSLog(@"objA = %@", objA);    //objA = null源码分析

autoreleasepool pop源码:


release中的源码:

总结:

  • 并不是全部对象都会被主动参加到AutoReleasePool
  • runloop周期竣事的时间AutoReleasePool会被开释
  • AutoReleasePool被开释时内里的对象会实行release操纵,但是并不肯定会开释
  • AutoReleasePool内里的对象要比及retainCount为0时间开释
  • AutoReleasePool内里的对象出作用域的时间并不会立即实行release操纵
  • for循环中的对象如果造成了内存暴增,可以用@autoreleasepool 参加到临时主动开释池
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-22 12:03, Processed in 0.180922 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表