iOS中内存管理(Autoreleasepool)

674 阅读3分钟

这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战

Autoreleasepool

Autoreleasepool用于存放那些需要在稍后某个时刻释放的对象,清空自动释放池时,系统会向其中的对象发送release消息

花括号定义了自动释放池的范围,左花括号开始创建,右花括号处自动释放,在此范围的末尾处,括号内的对象回收到`release`消息
@autoreleasepool{

}

注:这里只是发送一次release消息,如果当时引用计数不为0,则该对象依然不会释放

  • Autoreleasepool方法会返回对象本身(MRC)
    Penson *p = [Person new];
    p = [p autorelease];
    
  • 调用完Autoreleasepool 方法后,对象的计数器不变(MRC)
    Person *p = [Person new];
    p = [p autorelease];
    NSLog(@"count= %d",[p retainCount]);//1
    

Autoreleasepool的原理

Autoreleasepool 实际上只是release的调用延迟了,对于每一个Autoreleasepool,系统只是把该Object放入了当前的Autoreleasepool中,当pool被释放时,该pool中的所有Object会被调用release


Autoreleasepool的优点

  • 不用关心对象释放时间
  • 不用关心什么时候调用release
//创建一个自动释放池
@autoreleasepool{    

   Person *p = [[Person alloc]init];
   //不用关心对象什么时候释放,只要能够访问p的地方都可以使用p
   //只要调用了autorelease,那就不用调用release
   p = [p autorelease];
   
}
//自动释放池销毁了,给自动释放池中所有的对象发送一条release消息

Autoreleasepool的注意事项

  • 一定要在自动释放池中调用Autoreleasepool,才会将对象放入自动释放池(MRC)

  • 在自动释放池创建了对象,一定要调用Autoreleasepool,才会将对象放入自动释放池中(MRC)

    @autoreleasepool{
    Person *p =[[[Person alloc]init] autorelease];
    }
    
  • 不要在自动释放池中使用比较消耗内存的对象

    @autoreleasepool{
        Person *p =[[[Person alloc]init] autorelease];
        //n行代码
    }
    
  • 尽量不要再自动释放池中使用循环,特别的循环次数多的

    @autoreleasepool{
        for(int i= 0;i < 99999; i ++){
            //每次调用一次就会创建一个新的对象
            //每个对象都会占用一个存储块
            Person *p =[[[Person alloc]init] autorelease];
        }
    }
    //循环里创建对象会一直在池中,只有执行到这里才会释放
    
  • 一个程序中可以创建N个自动释放池,并且自动释放池可以嵌套,如果存在多个自动释放池,那么自动释放池会以“栈”的形式存储,先进后出

    @autoreleasepool{
        //创建第一个自动释放池
        @autoreleasepool{
            //创建第二个自动释放池
            @autoreleasepool{
                //创建第三个自动释放池
            }
            //销毁第一个自动释放池
        }
        //销毁第二个自动释放池
    }
    //销毁第三个自动释放池
    

合理利用Autoreleasepool可以降低内存峰值(ARC)

把循环内的代码包裹在Autoreleasepool中,那么在循环中自动释放对象就会放在这个池中,这样内存峰值就会降低(内存峰值:app在某个特定的时段内最大内存用量)

for(int i= 0;i < 99999; i ++){
    @autoreleasepool{
      Person *p =[[Person alloc]init];
      [array addObject:p];
    }
}

关于iOS内存管理相关知识点