使用CADisplayLink、NSTimer有什么注意點?
- 注意內存泄漏、循環(huán)引用的問題(self弱引用
timer會造成內存泄漏,強引用timer會造成循環(huán)引用) - 使用
NSProxy作為timer的target,然后弱引用self,打破循環(huán)引用的問題 -
NSProxy效率比NSObject高,專門用來做消息轉發(fā)的,會省略以下步驟:
1. 去父類尋找方法(本來NSProxy自身也沒其他方法了)
2. 動態(tài)方法解析階段
3. 消息轉發(fā)的第一步forwardingTargetForSelector - 最后直接來到消息轉發(fā)的第二步,執(zhí)行
methodSignatureForSelector有返回值再執(zhí)行forwardInvocation
介紹下內存的幾大區(qū)域講一下
- 低地址
- 保留:其他用途,大小由平臺決定(32位、64位)
- 代碼段(
__TEXT):編譯之后的代碼,例如函數 - 數據段(
__DATA):常量區(qū),比如全局變量、靜態(tài)變量 - 字符串常量:例如
NSString *str = @"123";(直接寫出來的,不是通過方法創(chuàng)建的那種字符串) - 已初始化數據:例如
static int a = 10;(定義就賦值的) - 未初始化數據:例如
static int b;(沒賦值的) - 堆
heap:通過alloc、malloc、calloc等動態(tài)分配的空間(實例對象),分配的內存空間地址【越來越大】 - 棧
stack:函數調用開銷,比如局部變量,分配的內存空間地址【越來越小】(先進后出) - 內核區(qū):系統(tǒng)內核相關的區(qū)域,只能系統(tǒng)訪問,例如讓線程休眠的操作
- 高地址

iOS程序的內存布局.jpg
你對 iOS 內存管理的理解
- 使用引用計數來管理OC對象的內存
- 一個新創(chuàng)建的
OC對象引用計數默認是1,當引用計數減為0,OC對象就會銷毀,釋放其占用的內存空間 - 調用
retain會讓OC對象的引用計數+1,調用release會讓OC對象的引用計數-1 - 內存管理的經驗總結:
- 當調用
alloc、new、copy、mutableCopy方法返回了一個對象,在不需要這個對象時,要調用release或者autorelease來釋放它 - 想擁有某個對象,就讓它的引用計數+1;不想再擁有某個對象,就讓它的引用計數-1

引用計數和weak引用的存儲.jpg
ARC 都幫我們做了什么?
-
ARC是LLVM編譯器和Runtime系統(tǒng)相互協(xié)助的一個結果
-LLVM:例如在某個作用域的{}即將結束的時候,自動對里面的對象調用release方法
-Runtime:例如weak指針的實現,在程序運行的過程中,監(jiān)控到對象要銷毀時會去清空對象的弱引用
weak指針的實現原理
-
weak指針會將弱引用存儲到一個哈希表(SideTable->weak_table)里面,當對象要銷毀時取出這個哈希表,把里面存儲的弱引用都清除掉 - 對象調用
dealloc時會判斷isa的weakly_referenced是否被弱引用過,有的話會調用clearDeallocating函數,根據當前對象的地址值通過哈希查找,找到對應的弱引用表,清除里面存儲的弱引用

copy和mutableCopy.jpg
autorelease對象在什么時機會被調用release
- 如果是自定義的
autoreleasepool,會在自動釋放池的{}結束前一刻調用release - 如果不是在自定義的
autoreleasepool,而是在main函數的autoreleasepool,是由RunLoop控制的,可能是在某次RunLoop循環(huán)中,在RunLoop休眠之前調用了release(kCFRunLoopBeforeWaiting)

autorelease時機(驗證).jpg

autorelease時機(原理).jpg

AutoreleasePoolPage的結構.jpg

dealloc的底層實現流程.jpg
方法里有局部對象, 出了方法后會立即釋放嗎
-
MRC環(huán)境下不會,會等RunLoop那次循環(huán)的休眠之前才釋放 -
ARC環(huán)境下會,LLVM會在方法的{}即將結束的時候,自動對里面的對象調用release方法