autorelease
autorelease 对象释放时机
在没有手加 Autorelease Pool 的情况下,Autorelease 对象是在当前的 runloop 迭代结束时释放的,而它能够释放的原因是系统在每个 runloop 迭代中都加入了自动释放池 Push 和 Pop
autorelease 原理
AutoreleasePoolPage
ARC 下,我们使用@autoreleasepool{}来使用一个 AutoreleasePool,随后编译器将其改写成下面的样子:
1 | void *context = objc_autoreleasePoolPush(); |
AutoreleasePoolPage 是一个 C++实现的类
1 |
|
向一个对象发送- autorelease 消息,就是将这个对象加入到当前 AutoreleasePoolPage 的栈顶 next 指针指向的位置
释放
- objc_autoreleasePoolPush()
每当进行一次 objc_autoreleasePoolPush 调用时,runtime 向当前的 AutoreleasePoolPage 中 add 进一个哨兵对象,值为 0(也就是个 nil)
objc_autoreleasePoolPush 的返回值正是这个哨兵对象的地址
- objc_autoreleasePoolPop(哨兵对象)
根据传入的哨兵对象地址找到哨兵对象所处的 page
在当前 page 中,将晚于哨兵对象插入的所有 autorelease 对象都发送一次 - release 消息,并向回移动 next 指针到正确位置
补充 2:从最新加入的对象一直向前清理,可以向前跨越若干个 page,直到哨兵所在的 page
嵌套的 AutoreleasePool
pop 的时候总会释放到上次 push 的位置为止,多层的 pool 就是多个哨兵对象而已,就像剥洋葱一样,每次一层,互不影响
autorelease