autorelease的对象与@autoreleasepool

首先,看两段代码执行之后,内存的变化:

1、

// 未使用@autoreleasepool
for (int i = 0; i < 100000; i ++) {
        UIImage *img = [UIImage imageNamed:@"test.jpg"];
        NSLog(@"%@", @(i));
    }

分析:imageName 返回的是 autorelease 的对象,因为我们一直处在循环中,因此它们将一直没有机会被释放。如果数量太多而且数据太大的时候,很容易因为内存不足而崩溃。若 for 循环中为 非autorelease 的对象,不会出现内存问题。
如下图,我们可以看到内存占用情况:

未使用@autoreleasepool.png

2、

// 使用@autoreleasepool
for (int i = 0; i < 100000; i ++) {
        @autoreleasepool {
            UIImage *img = [UIImage imageNamed:@"test.jpg"];
            NSLog(@"%@", @(i));
        }
    }

分析:这就涉及到 autorelease 的对象在什么时候释放的问题。
引用【在没有手加Autorelease Pool的情况下,Autorelease对象是在当前的runloop迭代结束时释放的,而它能够释放的原因是系统在每个runloop迭代中都加入了自动释放池Push和Pop】。对于我们手动添加的@autoreleasepol{},显然出了它的作用域之后对象就会被release。这里我们每一次循环都生成了一个自动释放池,虽然可以保证内存使用达到最小,但是释放过于频繁也会带来潜在的性能忧虑。一个折中的方法是将循环分隔开加入自动释放池,比如每10次循环对应一次自动释放,这样能减少带来的性能损失。
如下图,内存占用情况:

使用@autoreleasepool.png

什么时候用@autoreleasepool

根据Apple的文档,使用场景如下:

  1. 写基于命令行的的程序时,就是没有UI框架,如AppKit等Cocoa框架时。
  2. 写循环,循环里面包含了大量临时创建的对象。(本文的例子)
  3. 创建了新的线程。(非Cocoa程序创建线程时才需要)
  4. 长时间在后台运行的任务。

注:

1、什么是autorelease 的对象?
alloc、new、copy、mutableCopy四个内存管理的关键字,自身使用了这些关键字产生的对象都不是 autorelease 的对象,自身持有对象,那么不再需要时对象就会调用release方法释放对象;
不是通过上面关键字产生的都是 autorelease 的对象,底层会将该对象注册到 autoreleasepool 中,不会立即释放,会在pool结束时,释放对象。
2、参考
iOS内存管理
黑幕背后的Autorelease
@autoreleasepool-内存的分配与释放

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,142评论 1 32
  • 今天读的文章是剽悍晨读中的:只用1分钟就能战胜拖延症,不信你试试 说到拖延症,我很有发言权。因为我以前就是个严...
    Angela656阅读 262评论 0 0
  • 冬至已过,北方已入深冬了。 作为北方人,这意味着冰火两重天,痛苦又幸福的日子又来了—— 屋外冷风嗖嗖,屋里热带气候...
    跨界小咖阅读 585评论 0 0
  • 早上起来,将昨天晚上没有听完的《七个习惯》分享听完。 不知不觉,已至六月。 回首过往,如梦似幻,总觉不实。然,过往...
    时光南浔阅读 196评论 0 2