AutoreleasePool 与Runloop 关系
主线程默认会开启Runloop, Runloop 会自动帮我们创建AutoreleasePool,并进行Push,pop 等操作来进行内存管理。
ARC 下什么样的对象有autoreleasePool管理
第一种:当使用alloc/new/copy/mutableCopy 开始的方法进行初始化时,会生成并持有对象(也就是不需要pool管理,系统会在合适的位置release)。对于其他情况,例如:
id objc = [NSMutableArrayArray array];
#这种情况会自动将返回值的对象,注册到autoreleasepool,代码等效于
@autoreleasepool {
id __autorelease obj = [NSMutableArray array];
}
第二种:__weak 修饰符只持有对象的弱引用,而在访问引用对象的过程中,该对象可能被废弃,那么如果把对象注册到autoreleasepool 中,那么@autoreleasepool块结束之前能够确保对象的存在。例如:
id __weak obj1 = obj0;
NSLog(@“class=%@”,[obj class]);
#对应的模拟源码为:
id __weak obj1 = obj0;
id __autoreleaseing tmp = obj1;
NSLog(@“class = %@”, [tmp class]);
第三种:id 的指针或对象的指针在没有显示指定时会被附加__autoreleasing 修饰符
+ (nullable instancetype)stringWithContentsOfURL:(NSURL *)url
encoding:(NSStringEncoding)enc
error:(NSError **)error;
NSString *str = [NSString stringWithContentsOfURL:
encoding:
error:<#(NSError * _Nullable __autoreleasing * _Nullable)#>]
子线程默认不会开启Runloop,那么出现Autorelease 对象如何处理?不手动处理会内存泄漏吗?
简单阐述下,在子线程你创建了 Pool 的话,产生的 Autorelease 对象就会交给 pool 去管理。如果你没有创建 Pool ,但是产生了 Autorelease 对象,就会调用 autoreleaseNoPage 方法。在这个方法中,会自动帮你创建一个 hotpage(hotPage 可以理解为当前正在使用的 AutoreleasePoolPage,如果你还是不理解,可以先看看 Autoreleasepool 的源代码,再来看这个问题 ),并调用 page->add(obj) 将对象添加到 AutoreleasePoolPage 的栈中,也就是说你不进行手动的内存管理,也不会内存泄漏啦!StackOverFlow 的作者也说道,这个是 OS X 10.9+和 iOS 7+ 才加入的特性。
参考:
引用计数带来的一次讨论