__block修饰对象类型
int main(int argc, const char * argv[]) {
__block NSString * any = [NSString stringWithFormat:@"1"];
void (^test)() = ^ {
NSLog(@"%@",any);
};
test();
return 0;
}
编译结果:
结构示意图:
__block
修饰的对象数据类型的变量也能实现block内外同呼吸共患难,iOS Block Part4已经对同呼吸共患难的原理分析过了,这里就不做赘述了
int any;
NSString * any;
__block int any;
__block NSString * any;
前三种block捕获的数据类型我们已经讲过,而本篇的__block NSString * any
是这四种中最难.当然它也是最后的boss,把它学会了blcok
也就快通关了.
对比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
结构是一样的.
其实不然,struct __main_block_impl_0
的子结构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*);
以上两个方法对应的是:
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
拷贝与销毁.关于拷贝的具体流程后面会说.现在做一个关于拷贝的梳理:
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
所讲编译结果中所有提到的需要拷贝的地方.各种拷贝的具体实现请看下文.
参考文献:
Block技巧与底层解析 by tripleCC