美文网首页
关于autoreleasepool内存管理

关于autoreleasepool内存管理

作者: Harry_Coding | 来源:发表于2019-02-18 18:00 被阅读0次

    首先要从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

    相关文章

      网友评论

          本文标题:关于autoreleasepool内存管理

          本文链接:https://www.haomeiwen.com/subject/astzeqtx.html