四 __block的底层实现
前言
本文是block系列的最后一篇,我们知道block有个特性,在block代码体内部不能修改所捕获的外部非静态局部变量的值(全局变量和静态局部变量的值可以修改),如果想修改,需要在变量前面加上__block,本文主要讲述__block的作用和实现原理。
block的底层实现
先看代码:
int main(int argc, const char * argv[]) {
__block int d = 100;
__block Person *person = [[Person alloc]init];
void (^block2)(void) = ^{
d = 200;
person = nil;
};
return 0;
}
int main(int argc, const char * argv[]) {
__Block_byref_d_0 d = {
(void*)0,
(__Block_byref_d_0 *)&d,
0,
sizeof(__Block_byref_d_0),
100};
__Block_byref_person_1 person = {
(void*)0,
person,
33554432,
sizeof(__Block_byref_person_1),
__Block_byref_id_object_copy_131,
__Block_byref_id_object_dispose_131,
[[Person alloc]init]};
block2 = __main_block_impl_0(
__main_block_func_0,
__main_block_desc_0,
d,
person);
return 0;
}
struct __Block_byref_d_0 {
void *__isa;
__Block_byref_d_0 *__forwarding;
int __flags;
int __size;
int d;
};
struct __Block_byref_person_1 {
void *__isa;
__Block_byref_person_1 *__forwarding;
int __flags;
int __size;
void (*__Block_byref_id_object_copy)(void*, void*);
void (*__Block_byref_id_object_dispose)(void*);
Person *__strong person;
};
通过观察代码,我们知道,甭管是int类型还是Person类型,添加上__block后,这些自动变量都被包装成了struct _Block_byref**,而这个结构内部,有isa指针,且采用值复制的方式复制了int和person指针的值,基本类型和引用类型的区别在于,引用类型的结构体中多了两个函数指针copy和dispose,这两个指针是用来管理person的引用计数的。所以__block添加后,局部变量被包裹了一层,变成了OC对象,其内存引用关系图如下所示:
至此,block的内容介绍完毕,如发现疏漏,欢迎沟通交流。