__block修飾對象類型
int main(int argc, const char * argv[]) {
__block NSString * any = [NSString stringWithFormat:@"1"];
void (^test)() = ^ {
NSLog(@"%@",any);
};
test();
return 0;
}
編譯結(jié)果:
結(jié)構(gòu)示意圖:
__block
修飾的對象數(shù)據(jù)類型的變量也能實現(xiàn)block內(nèi)外同呼吸共患難,iOS Block Part4已經(jīng)對同呼吸共患難的原理分析過了,這里就不做贅述了
int any;
NSString * any;
__block int any;
__block NSString * any;
前三種block捕獲的數(shù)據(jù)類型我們已經(jīng)講過,而本篇的__block NSString * any
是這四種中最難.當(dāng)然它也是最后的boss,把它學(xué)會了blcok
也就快通關(guān)了.
對比block(__block int
與block(__block NSString * any)
編譯生成的struct __main_block_impl_0
block(__block int)
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_any_0 *any;
}
block(__block NSString * any)
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_any_0 *any;
}
看上去編譯生成的struct __main_block_impl_0
結(jié)構(gòu)是一樣的.
其實不然,struct __main_block_impl_0
的子結(jié)構(gòu)struct __Block_byref_any_0
雙方有很大的不一樣.
block(__block int)
struct __Block_byref_any_0 {
void *__isa;
__Block_byref_any_0 *__forwarding;
int __flags;
int __size;
int any;
};
block(__block NSString * any)
struct __Block_byref_any_0 {
void *__isa;
__Block_byref_any_0 *__forwarding;
int __flags;
int __size;
void (*__Block_byref_id_object_copy)(void*, void*);
void (*__Block_byref_id_object_dispose)(void*);
NSString *any;
};
block(__block NSString * any)
編譯所得的struct __Block_byref_any_0
多出兩個方法:
void (*__Block_byref_id_object_copy)(void*, void*);
void (*__Block_byref_id_object_dispose)(void*);
以上兩個方法對應(yīng)的是:
static void __Block_byref_id_object_copy_131(void *dst, void *src) {
_Block_object_assign((char*)dst + 40, *(void * *) ((char*)src + 40), 131);
}
static void __Block_byref_id_object_dispose_131(void *src) {
_Block_object_dispose(*(void * *) ((char*)src + 40), 131);
}
這兩個方法的作用是:block(__block NSString * any)
編譯生成的struct __Block_byref_any_0
->NSString *any
拷貝與銷毀.關(guān)于拷貝的具體流程后面會說.現(xiàn)在做一個關(guān)于拷貝的梳理:
block(int any)
struct __main_block_impl_0需要拷貝
block(NSString * any)
struct __main_block_impl_0需要拷貝
NSString * any需要拷貝
block(__block int any)
struct __main_block_impl_0需要拷貝
struct __Block_byref_any_0需要拷貝
block(__block NSString * any)
struct __main_block_impl_0需要拷貝
struct __Block_byref_any_0需要拷貝
NSString * any需要拷貝
這是iOS Block Part2
到iOS Block Part5
所講編譯結(jié)果中所有提到的需要拷貝的地方.各種拷貝的具體實現(xiàn)請看下文.
參考文獻(xiàn):
Block技巧與底層解析 by tripleCC