Block
block 類型
**1饰躲、全局block - **NSGlobalBlock****
**2、棧block -NSStackBlock **
**3槽奕、堆block - **NSMallocBlock****
總結(jié)
block直接存儲在全局區(qū)
如果block訪問外界變量,并進行block相應拷貝,即copy
如果此時的block是強引用嫉沽,則block存儲在堆區(qū),即堆區(qū)block
-
如果此時的block通過__weak變成了弱引用俏竞,則block存儲在棧區(qū)绸硕,即棧區(qū)block
解決block循環(huán)引用的方法 自動釋放 如果block內(nèi)部嵌套block,需要同時使用__weak 和 **strong
雖然**weak,解決了block里面的循環(huán)引用問題魂毁,但是在延遲操作的時候玻佩,保證不了name的生命周期,所以這時候是null席楚,這時候就要結(jié)合__strong 來使用
weak-strong-dance 強弱共舞
手動釋放
利用臨時變量打破block->self的持有
利用VC進行通訊
NSProxy 虛擬類
NSProxy 其實是一個消息重定向封裝的一個抽象類咬崔,類似一個代理人,中間件,可以通過繼承它垮斯,并重寫下面兩個方法來實現(xiàn)消息轉(zhuǎn)發(fā)到另一個實例
循環(huán)引用解決原理
自定義一個NSProxy的子類CJLProxy
block底層分析
通過xcrun -sdk iphonesimulator clang -arch x86_64 -rewrite-objc block.c郎仆,將block.c 編譯成 block.cpp,其中block在底層被編譯成了以下的形式
這里說明了block必須調(diào)用
訪問外界局部變量
這里會造成編譯器代碼歧義兜蠕,只讀
__block修飾后
block的結(jié)構(gòu)
Block_layout
descriptor1扰肌,通過指針編譯,可以獲取到descriptor2熊杨,copy和dipose在這里
descriptor3曙旭,block的簽名在這里
block變化的流程
開始是一個全局的block,但是訪問了外部局部變量晶府,變成棧block桂躏,之后在系統(tǒng)內(nèi)部,objc_retainblock里面川陆,系統(tǒng)進行了copy的操作剂习,外部默認是strong修飾的,所以出objc_retainblock的時候较沪,就變成了堆block
_Block_copy
把參數(shù)轉(zhuǎn)成block_layout類型鳞绕,如果是全局block那么直接返回,再之后只有棧區(qū)block了购对,因為堆區(qū)block是需要申請開辟空間的猾昆,進入棧的判斷,這里進行了malloc申請開辟空間骡苞,進行memmove平移垂蜗,copy變成堆區(qū)block
block的三層copy
1、首先blcok對外部變量的一次copy解幽,到堆區(qū)
2贴见、因為block修飾的外部變量變成了_block_byref的結(jié)構(gòu)體,這一次對這個結(jié)構(gòu)體進行copy
3躲株、如果外部變量是一個對象的話片部,那么就會進行第三次copy,對這個對象進行copy到block內(nèi)部
blcok對外界變量的捕獲
首先判斷對象類型霜定,byref是block修飾后的類型