Autorelease 对象的内存管理

2020-02-23  本文已影响0人  TaoGeNet

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+ 才加入的特性。

参考:
引用计数带来的一次讨论

上一篇下一篇

猜你喜欢

热点阅读