之所以将这三个东西放到一起说,主要是由于息息相关,互相影响,互相依赖。
Autorelease
What:是一种支持引用技术的内存管理方式。使被标示autorelease的对象在可以被销毁的时候放入最近的(栈顶的)释放池,等待释放。是一种延时释放,提高系统性能。
When:在没有手加autorelease pool的情况下,autorelease对象是在当前的runloop迭代结束时释放的,而它能够释放的原因是系统在每个runloop迭代中都加入了自动释放池Push和Pop。(autorelease并不是根据作用域来决定释放时机的,而是依据runloop来决定释放时机的。)
Where:ARC下就加在可以自动添加autorelease的对象被创建出来的时候。
Why:OC的内存管理机制中比较重要的一条规律是:谁申请,谁释放。考虑这种情况,如果一个方法需要返回一个新建的对象,该对象何时释放?方法内部是不会写release来释放对象的,因为这样做会将对象立即释放而返回一个空对象;调用者也不会主动释放该对象的,因为调用者遵循“谁申请,谁释放”的原则。那么这个时候,就发生了内存泄露。针对这种情况,Objective-C的设计了autorelease,既能确保对象能正确释放,又能返回有效的对象。
在autorelease的模式下,代码如下:
ClassA *Func1()
{
ClassA *obj = [[[ClassA alloc]init]autorelease];
return obj;
}
Autorelease Pool:
What:是OC的一种内存自动回收机制,可以将一些临时变量通过自动释放池来回收统一释放。自动释放池本身销毁的时候,池子里面所有的对象都会做一次release操作。
自动释放池以栈的形式实现:当你创建一个新的自动释放池时,它将被添加到栈顶。接收autorelease消息的对象将被放入到最顶端的自动释放池中。如果将一个对象放入一个自动释放池中,然后创建一个新的自动释放池再销毁该新建的自动释放池,则这个自动释放对象仍将存在,因为容纳该对象的自动释放池仍然存在。
When: 当出了@autoreleasepool{ ··· }的作用域时,当前autoreleasepool被drain。所有的release pool会构成一个像CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的autorelease pool会被销毁,这样这个pool里的每个Object会被release。
黄金法则:如果对一个对象使用了alloc、[mutable]copy、retain,那么必须使用相应的release或者autorelease。ARC下autorelease被自动添加。
Why:见autorelease,原因相同。
注意:在主线程的 NSRunLoop 对象(在系统级别的其他线程中应该也是如此,比如通过 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 获取到的线程)的每个 event loop 开始前,系统会自动创建一个 autoreleasepool,并在event loop结束时drain。另外,NSAutoreleasePool 中还提到,每一个线程都会维护自己的 autoreleasepool 堆栈。换句话说 autoreleasepool 是与线程紧密相关的,每一个 autoreleasepool 堆栈只对应一个线程。
Runloop:
What:轮训,在线程中不停地对事件进行观察,做出响应,其余内容暂不讨论。
其他:
在iOS中有三种常用的遍历方法:for、forin、enumerateObjectsUsingBlcok;block版本的遍历方式已经内嵌了@autoreleasepool{}操作,而前面两个没有,这样就意味着使用block版本的遍历方式会使app更加健壮,内存使用效率更加出色。
网友评论