Block使用要點,block要點
Block簡介
Block其實包含兩個部分內容
Block在記憶體中的位置
根據Block在記憶體中的位置分為三種類型NSGlobalBlock,NSStackBlock, NSMallocBlock。
- NSGlobalBlock:類似函數,位於text段;
- NSStackBlock:位於棧記憶體,函數返回後Block將無效;
- NSMallocBlock:位於堆記憶體。
Block被另一個Block使用時,另一個Block被copy到堆上時,被使用的Block也會被copy。但作為參數的Block是不會發生copy的。Block對不同類型的變數的存取基本類型
適用於MRC和ARC的情況
- 局部自動變數,在Block中唯讀。Block定義時copy變數的值,在Block中作為常量使用,所以即使變數的值在Block外改變,也不影響他在Block中的值。
- static變數、全域變數。Block就可以對它們進行讀寫了。因為全域變數或靜態變數在記憶體中的地址是固定的,Block在讀取該變數值的時候是直接從其所在記憶體讀出,擷取到的是最新值,而不是在定義時copy的常量。
- Block變數,被
__block
修飾的變數稱作Block變數。 基本類型的Block變數等效於全域變數、或靜態變數。
ObjC對象
不同於基本類型,Block會引起對象的引用計數變化。
MRC:
- 局部自動變數,在Block copy時,系統自動retain對象,增加其引用計數。
- static變數,全域變數,在記憶體中的位置是確定的,所以Block copy時不會retain對象。
- Block變數,在Block copy時也不會retain。
- 執行個體變數,在Block copy時也沒有直接retain 執行個體變數對象本身,但會retain 執行個體變數的擁有者self。所以在Block中可以直接讀寫 執行個體變數。
ARC:
- 只有在使用local變數時,block會複製指標,且強引用指標指向的對象一次。其它如全域變數、static變數等,block不會拷貝指標,只會強引用指標指向的對象一次。
__block變數,在Block copy時
會retain__block變數
struct __Block_byref_intValue_0{ void *__isa; __Block_byref_intValue_0 *__forwarding; int __flags; int __size; int intValue;};struct __main_block_impl_0{ struct __block_impl impl; struct __main_block_desc_0* Desc; __Block_byref_intValue_0 *intValue; // by ref __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_intValue_0 *_intValue, int flags=0) : intValue(_intValue->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; }};
- 標記了為__weak或__unsafe_unretained的local變數。block仍會強引用指標對象一次。
參考:http://my.oschina.net/u/1432769/blog/390401?fromerr=QO9ABGMC
http://tanqisen.github.io/blog/2013/04/19/gcd-block-cycle-retain/