写这边文章的原因是看到网络上对于AutoReleasePool讨论,发现大家对AutoReleasePool存在误区。
AutoReleasePool 里面的对象何时释放?
这个问题是常见的iOS面试题,错误的答案:
1.等到一次runloop结束,AutoReleasePool被释放时
2.超出作用域{}
这些答案都不对,标准答案:
每次release时retainCount减一,当retainCount为0时候释放对象。release的时机比如runloop周期中AutoReleasePool被释放时,比如超出作用域时
关键概念点:
1. 不是所有OC对象都会加入到AutoReleasePool
2. AutoReleasePool被释放时里面的对象不一定会释放,超出作用域一样不一定会释放
__weak id objA = nil;
{
id objB = [NSObject new];
objA = objB;
}
NSLog(@"%@", objA);
// objA = null
这个是没有异议的情况,objB出了作用域就会被释放,但是下面的代码就不一样了
id objA = nil;
@autoreleasepool {
id objB = [NSObject new];
objA = objB;
}
NSLog(@"%@", objA);
// objA = <NSObject: 0x600002708330>
objB虽然被加入到自动释放池,但是并不会被释放掉,因为还有objA在强引用它。如果这里的objA是weak的,objB会被释放
__weak id objA = nil;
{
__autoreleasing id objB = [NSObject new];
objA = objB;
}
NSLog(@"%@", objA);
// objA = <NSObject: 0x600000c545c0>
objA虽然是弱引用,但是__autoreleasing的AutoReleasePool是和objA同级的,要等AutoReleasePool释放的时候objB才会被释放,即使objB已经出了作用域,其实这里出作用域的时候并没有执行release操作
__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中的源码:
总结: