在开发中经常使用block,先看一下简单基本使用:
void test1()
{
int a = 10;
void (^block)() = ^{
NSLog(@"%d", a);
};
a = 20;
block(); //输出结果是 10
}
void test2()
{
__block int a = 10;
void (^block)() = ^{
NSLog(@"%d", a);
};
a = 20;
block(); //输出结果是 20
}
void test3()
{
static int a = 10;
void (^block)() = ^{
NSLog(@" %d", a);
};
a = 20;
block(); // 输出结果20
}
// a 是一个全局的变量
int a = 10;
void test4()
{
void (^block)() = ^{
NSLog(@"a is %d", a);
};
a = 20;
block();//输出结果为20
}
简单的main函数
int main(int argc,const char * argv[]) {
@autoreleasepool {
test4();
}
return 0;
}
在main函数中调用test1,将main.m转换为main.cpp后 在cpp文件中可以看到test1函数:
void test1()
{
int a = 10;
//_test1_block_impl_0 是一个c++的结构体,调用了这个歌结构体的构造函数,构造函数的第一个参数是传递的一个C++函数这个函数是用来保存block中的代码,函数结构见下面__test1_block_func_0
void (*block)() = ((void (*)())&__test1_block_impl_0((void *)__test1_block_func_0, &__test1_block_desc_0_DATA, a)); 在block中将a的值传递了进去,所以在调用block的时候输出的值是10
a = 20;
//3.当我们调用block的时候 我们其实调用的就是这个函数FuncPtr
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}
<pre name="code" class="cpp">struct __test1_block_impl_0 {
struct __block_impl impl;
struct __test1_block_desc_0* Desc;
int a;
// 2.__test1_block_impl_0结构体的构造函数,第一个参数赋值给了FuncPtr
__test1_block_impl_0(void *fp, struct __test1_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
block中的代码 编译器会编译成一个函数保存,
static void __test1_block_func_0(struct __test1_block_impl_0 *__cself) {
int a = __cself->a; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_36_fw4zn5v15w10psb207f993_c0000gn_T_main_f13c04_mi_0, a);
}
由此可见block中保存的是一个指向结构体的指针,这个结构体中保存有装有block种代码的函数
在main.m中调用test2 转换为main.cpp文件后:
void test2()
{
__attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 10};
// 可以看到__test2_block_impl_0 结构体构造函数中传入的是变量a的地址,所以在block之后变量a的值发生更改,之后block中输出的是最新的值
void (*block)() = ((void (*)())&__test2_block_impl_0((void *)__test2_block_func_0, &__test2_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
(a.__forwarding->a) = 20;
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}
同理在main.m 中调用test3 转换为main.cpp文件后:
void test3()
{
static int a = 10;
// 可以看到__test3_block_impl_0 结构体构造函数中传入的是变量a的地址,所以在block之后变量a的值发生更改,之后block中输出的是最新的值>
void (*block)() = ((void (*)())&__test3_block_impl_0((void *)__test3_block_func_0, &__test3_block_desc_0_DATA, &a));
a = 20;
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}
同理在main.m中调用test4 转换为main.cpp文件后:
int a = 10;//<span style="color:#ff0000;">全局变量</span>
struct __test4_block_impl_0 {
struct __block_impl impl;
struct __test4_block_desc_0* Desc;
__test4_block_impl_0(void *fp, struct __test4_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __test4_block_func_0(struct __test4_block_impl_0 *__cself) {
//只有在最终调用函数中的代码的时候直接输出a的值</span>
NSLog((NSString *)&__NSConstantStringImpl__var_folders_36_fw4zn5v15w10psb207f993_c0000gn_T_main_6730fe_mi_0, a);
}
static struct __test4_block_desc_0 {
size_t reserved;
size_t Block_size;
} __test4_block_desc_0_DATA = { 0, sizeof(struct __test4_block_impl_0)};
void test4()
{
void (*block)() = ((void (*)())&__test4_block_impl_0((void *)__test4_block_func_0, &__test4_block_desc_0_DATA));
a = 20;
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}