关于autoreleasepool内存管理

2019-02-18  本文已影响0人  Harry_Coding

首先要从MRC说起,我们都知道MRC阶段,内存管理都是有程序猿手动管理的;那么就必须要说到内存管理的黄金法则:

  1. 自己生成的对象,自己持有(通过alloc/new/copy/mutableCopy)retain **
  2. 非自己生成的对象,自己也能持有(除了以alloc/new/copy/mutableCopy开头的方法)
  3. 不再需要持有自己持有对象时释放 release
  4. 无法释放非自己持有的对象
    当然到了ARC时期,编译器帮我们做了这些事情,当然关于autorelease的事情也是编译帮我做的。
  1. autoreleasepool是什么?
    自动释放池,像数据结构栈一样的结构,autorelease对象push到自动释放池,非手动创建的情况下,自动释放池会在runloop迭代结束的时候对“哨兵对象”之后的autorelease对象进行一次release操作,autorelease也会在runloop迭代结束释放。手动创建的autoreleasepool会在大括弧结束进行释放。
  2. 什么对象会加入到autoreleasepool?
    MRC时期我们可以采用[objc autorelease], 加入到当前的自动释放池。ARC不在需要,也不允许我们如此加入,编译器会自动给我加入。那么什么对象是autorelease对象?即“黄金法则”第二条,非alloc/new/copy/mutableCopy开头的构造方法生成的对象都会先加入到autoreleasePool,比如[NSMutableArray array]、[UIImage imageNamed:@"xxx"]、[NSString stringWithFormat:@"test stringq"]
  3. 什么情况下需要手动创建autoreleasePool
    根据官方文档总共有三条情况下我们需要创建autoreleasepool。
    • 基于命令行的程序
    • 创建辅助线程
    • for 循环中创建大量的autorelease对象
  4. 验证一下
@implementation ViewController

__weak NSString *__weakString = nil;
__weak UIImage *__weakImage = nil;

- (void)viewDidLoad {
  [super viewDidLoad];
// 1.
//    NSString *string = [NSString stringWithFormat:@"haoYuhong--------计算机丝是"];
//    UIImage *image = [UIImage imageNamed:@"bofang-2"];
//    __weakString = string;
//    __weakImage = image;

  // 2.
  @autoreleasepool {
      UIImage *image = [UIImage imageNamed:@"bofang-2"];
      NSString *string = [NSString stringWithFormat:@"haoYuhong--------计算机丝是"];
//        NSString *string = [NSString stringWithFormat:@"haoYuhong"];
      __weakImage = image;
      __weakString = string;
  }
  
  NSLog(@"%@", __weakString);
  NSLog(@"%@", __weakImage);
}

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  NSLog(@"%@", __weakString);
  NSLog(@"%@", __weakImage);
}

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  NSLog(@"%@", __weakString);
  NSLog(@"%@", __weakImage);
}

第一种情况下,我们会看到

2019-02-18 17:11:09.134399+0800 AutoreleasePool[25252:4061510] haoYuhong--------计算机丝是
2019-02-18 17:11:09.134563+0800 AutoreleasePool[25252:4061510] <UIImage: 0x6040000b1580>, {200, 200}
2019-02-18 17:11:09.134749+0800 AutoreleasePool[25252:4061510] haoYuhong--------计算机丝是
2019-02-18 17:11:09.134897+0800 AutoreleasePool[25252:4061510] <UIImage: 0x6040000b1580>, {200, 200}
2019-02-18 17:11:09.139543+0800 AutoreleasePool[25252:4061510] (null)
2019-02-18 17:11:09.139678+0800 AutoreleasePool[25252:4061510] (null)

第二种情况输出:

2019-02-18 17:12:24.893067+0800 AutoreleasePool[25284:4063032] (null)
2019-02-18 17:12:24.893245+0800 AutoreleasePool[25284:4063032] (null)
2019-02-18 17:12:24.893472+0800 AutoreleasePool[25284:4063032] (null)
2019-02-18 17:12:24.893592+0800 AutoreleasePool[25284:4063032] (null)
2019-02-18 17:12:24.897735+0800 AutoreleasePool[25284:4063032] (null)
2019-02-18 17:12:24.897892+0800 AutoreleasePool[25284:4063032] (null)

在没有手动添加autoreleasepool的情况下,编译自动将添加autorelease对象到主线程的自动释放池,所以对象会延迟释放。当手动添加autoreleasepool的情况下,作用域结束之后就就会释放一次,当前pool中的autorelease对象。

注意:为什么NSString对象长度我要保持在>9呢?<=9会是什么情况,这里边其中有大奥秘,点击这里看我的另一篇文章

关于autoreleasePool的源码解析,其实千篇一律,道理都是一样的,许许多多的人都写过了,也分析了。这里我将我阅读的解析源码大神的文章附上:

黑幕背后的Autorelease
https://www.jianshu.com/p/66282c943c04

上一篇下一篇

猜你喜欢

热点阅读