autoreleasepool
#iOS笔记/复习笔记
使用形式
// OC
@autoreleasepool {
// 生成自动释放对象
}
// swift
autoreleasepool {
// 生成自动释放对象
}
AutoreleasePoolPage 结构
AutoreleasePoolPage 是一个 C++ 中的类,在NSObject.mm 中的定义是这样的:
class AutoreleasePoolPage {
// 对当前AutoreleasePoolPage 完整性的校验
magic_t const magic;
// 指向下一个即将产生的autoreleased对象的存放位置(当next == begin()时,表示AutoreleasePoolPage为空;当next == end()时,表示AutoreleasePoolPage已满
id *next;
// 当前线程,表明与线程有对应关系
pthread_t const thread;
// 指向父节点,第一个节点的 parent 值为 nil;
AutoreleasePoolPage * const parent;
// 指向子节点,最后一个节点的 child 值为 nil;
AutoreleasePoolPage *child;
// 代表深度,第一个page的depth为0,往后每递增一个page,depth会加1;
uint32_t const depth;
// 表示high water mark(最高水位标记)
uint32_t hiwat;
};
从上述的结构可以知道,其实每一个AutoreleasePool都是以AutoreleasePoolPage
为节点用双向链表的形式连接起来的。
每个AutoreleasePoolPage对象有4096字节的存储空间, 除了存放它自己的成员变量(56 个字节,每个占 8 个字节)外, 剩下的空间用来存储后面加入的autorelease对象。
大致流程
- 当进入
@autoreleasepool作用域时,objc_autoreleasePoolPush方法被调用,runtime会向当前的AutoreleasePoolPage中添加一个nil对象作为哨兵对象,并返回该哨兵对象的地址; - 对象调用
autorelease方法,会被加入到对应的AutoreleasePoolPage中,next指针类似一个游标,不断变化,记录位置,如果加入的对象超出一页大小,便会自动添加一个新页面; - 当离开
@autoreleasepool作用域时,objc_autoreleasePoolPop:(哨兵对象地址)方法被调用,其会从当前page的next指标的上一个元素开始查找,一直找到最近的一个哨兵对象,依次向这个范围中的对象发送release消息;
因为哨兵对象的存在,自动释放池的嵌套也是满足的,不管是嵌套,还是被嵌套的自动释放池,找到自己对应的哨兵对象就行了;
iOS探究 - autorelease 和 autoreleasepool - 简书 AutoreleasePool - 掘金