AutoreleasePool的創(chuàng)建和釋放
創(chuàng)建
App啟動(dòng)后暇咆,蘋果在主線程 RunLoop 里注冊(cè)了兩個(gè) Observer谤牡,其回調(diào)都是
_wrapRunLoopWithAutoreleasePoolHandler()副硅。
第一個(gè) Observer 監(jiān)視的事件是 Entry(即將進(jìn)入Loop),其回調(diào)內(nèi)會(huì)調(diào)用
_objc_autoreleasePoolPush() 創(chuàng)建自動(dòng)釋放池翅萤。優(yōu)先級(jí)最高恐疲,保證創(chuàng)建釋放池發(fā)生在其他所有回調(diào)之前。
釋放
第二個(gè) Observer 監(jiān)視了兩個(gè)事件: BeforeWaiting(準(zhǔn)備進(jìn)入休眠)
時(shí)調(diào)用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush()
釋放舊的池并創(chuàng)建新池套么;
Exit(即將退出Loop) 時(shí)調(diào)用 _objc_autoreleasePoolPop() 來釋放自動(dòng)釋放池培己。優(yōu)先級(jí)最低,保證其釋放池子發(fā)生在其他所有回調(diào)之后胚泌。
在主線程執(zhí)行的代碼省咨,通常是寫在諸如事件回調(diào)、Timer回調(diào)內(nèi)的玷室。這些回調(diào)會(huì)被 RunLoop 創(chuàng)建好的 AutoreleasePool 環(huán)繞著零蓉,所以不會(huì)出現(xiàn)內(nèi)存泄漏,開發(fā)者也不必顯示創(chuàng)建 Pool 了穷缤。
內(nèi)部實(shí)現(xiàn)
@ autoreleasepool {
//AutoreleasePoolPage是C++類,調(diào)用它里面的push方法
void *ctx = objc_autoreleasePoolPush(){
void *objc_autoreleasePoolPush(void)
void *AutoreleasePoolPage::push(void)
};
//調(diào)用AutoreleasePoolPage中的pop函數(shù),一次pop實(shí)際上相當(dāng)于一次批量的pop操作
objc_autoreleasePoolPop(ctx){
void objc_autoreleasePoolPop(void *ctxt)
AutoreleasePoolPage::pop(void *ctxt)
};
}
在autoreleasepool中的所有對(duì)象,都會(huì)添加到自動(dòng)釋放池中,當(dāng)進(jìn)行pop之后, autoreleasepool中所有對(duì)象都會(huì)被發(fā)送一次release消息
AutoreleasePoolPage
- 最下面是自身占用內(nèi)存,上面是用來存儲(chǔ)AutoreleasePool中填充的對(duì)象
- next指針指向當(dāng)前棧的空位置
- 每次進(jìn)行AutoreleasePool的代碼塊創(chuàng)建的時(shí)候,相當(dāng)于在棧中去插入一個(gè)【哨兵對(duì)象】
- 進(jìn)行入棧操作時(shí),添加到next指針?biāo)赶虻奈恢玫蟹洌缓髇ext上移
[obj autorelease]方法實(shí)現(xiàn)
- 當(dāng)一個(gè)對(duì)象的調(diào)用了autorelease方法,會(huì)將該對(duì)象添加到棧頂?shù)淖詣?dòng)釋放池中
- 當(dāng)自動(dòng)釋放池被回收時(shí),池子里面所有對(duì)象的使用都會(huì)做一次release操作
AutoreleasePoolPage中Pop方法的實(shí)現(xiàn)
runloop將要結(jié)束的時(shí)候調(diào)用AutoreleasePoolPage的pop()方法:
- 哨兵對(duì)象出棧
- 池子里面所有對(duì)象的使用都會(huì)做一次release操作
- next指針下移