void *fp:函数指针
struct __ZMX__blockTest_block_desc_0 *desc: desc结构体
int _a: 变量
int flags=0:标识 可以不传
我们通过简化block的定义:
void (*blcok)() = ((void (*)())&__ZMX__blockTest_block_impl_0((void *)__ZMX__blockTest_block_func_0, &__ZMX__blockTest_block_desc_0_DATA, a));
可以看到,我们在定义的时候就已经将a作为参数传递进去了。也就是在定义的时候我们的block就获取到了a的值,而且不管后面怎么修改a的值。我们在block内部获取的a都是定义的时候传进来的值,这也就导致为什么block可以捕获局部变量却不可以修改的原因
2.1 全局变量 可以被捕获也可以修改
(void)blockTest
{
void (^blcok)() = [^{
NSLog(@"%d",a);
} copy];
a = 20;
blcok(); // log : 20
}
我们用clang转化之后看看

一样的部分我就不重复了,我们可以看到这个时候定义blcok的构造函数是没有传入之前的参数a
我们调用NSLog函数 = 上面__ZMX__blockTest_block_func_0函数
static void __ZMX__blockTest_block_func_0(struct __ZMX__blockTest_block_impl_0 *__cself) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_47_6nlw9jbn3fb7c8lb1km1rzmm0000gn_T_ZMX_70ee3a_mi_0,a);
}
很显然,在我们调用block的时候,如果你之前有修改a的值,那打印的一定是新值
2.2 静态变量 可以被捕获也可以修改
(void)blockTest
{
static int a = 10;
void (^blcok)() = [^{
NSLog(@"%d",a);
} copy];
a = 20;
blcok(); //log : 20
}
我们用clang转化之后看看

通过构造函数我们可以看到,这时候入参多了一个int *_a,传递的是a的地址了。打印的函数__ZMX__blockTest_block_func_0也一样,都是获取到同一内存地址上的值操作。so,我们既可以访问a同时也可以修改a了
2.3 __block修饰的变量 可以被捕获也可以修改
(void)blockTest
{
__block int a = 10;
void (^blcok)() = [^{
NSLog(@"%d",a);
} copy];
a = 20;
blcok();// log : 20
}
我们用clang转化之后看看

哎!这时候的结构体__ZMX__blockTest_block_impl_0的a变成了一个结构体指针。好奇怪,我们来看一下这个结构体










