自动释放池的原理和本质
什么是 autoreleasepool
?
答:autoreleasepool
是 OC
的内存自动管理机制,它可以通过把不需要立即释放的对象通过栈的形式放到自动释放池中,当代码执行到释放池作用域结束,将池中的对象统一发送 release
消息,当对象的引用计数为零时,对象就被释放,内存被系统回收.
autoreleasepool
的本质其实也是一个对象
,
struct __AtAutoreleasePool {
//构造函数
__AtAutoreleasePool() {
atautoreleasepoolobj = objc_autoreleasePoolPush();
}
//析构函数
~__AtAutoreleasePool() {
objc_autoreleasePoolPop(atautoreleasepoolobj);
}
// 结构体定义的对象
void * atautoreleasepoolobj;
};
@autoreleasepool {}
//等价于
{__AtAutoreleasePool __autoreleasepool; }
__AtAutoreleasePool
是一个结构体,有构造函数和析构函数autoreleasepool
在加入要释放的对象时,底层调用的是objc_autoreleasePoolPush
方法autoreleasepool
在调用析构函数释放时,内部的实现是调用objc_autoreleasePoolPop
方法栈为节点,通过
双向链表
构成
不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)
分两种情况:手动干预释放时机、系统自动去释放
手动干预释放时机:指定
autoreleasepool
就是所谓的:当前作用域大括号结束时就立即释放系统自动去释放:不手动指定
autoreleasepool
,Autorelease
对象会在当前的runloop
迭代结束时释放,下面详细说明释放时机-
RunLoop
中的三个状态会处理自动释放池,通过打印代码发现有两个Observer
监听到状态值为:1和160(32+128)-
kCFRunLoopEntry
(1) // 第一次进入会创建一个自动释放池 -
kCFRunLoopBeforeWaiting
(32) // 进入休眠状态前先销毁自动释放池,再创建一个新的自动释放池 -
kCFRunLoopExit
(128) // 退出RunLoop
时销毁最后一次创建的自动释放池
-
在每一次
runloop
循环将要结束时,会对前一次创建的AutoreleasePool
进行pop
操作,同时会push
进来一个新的AutoreleasePool
,所以在viewDidLoad
中所创建的array
对象,是在当次runloop
将要结束的时候,调用AutoreleasePoolPage
的pop
方法中释放的