1. block的本质
block是将函数及其执行上下文封装起来的对象
1. 基本使用
int age = 10;
void (^block)(void)=^{
NSLog(@"----%d",age);
};
block();
2.转成.cpp文件
int age = 10;
/*
void (^block)(void)=^{
NSLog(@"----%d",age);
};
*/
void (*block)(void)=((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, age));
/***block();****/
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
/*
//去掉类型转换
int age = 10;
void (*block)(void)=(
&__main_block_impl_0
(
__main_block_func_0,
&__main_block_desc_0_DATA,
age
)
);
((block)->FuncPtr)(block);
*/
由代码可以看出:
- 定义一个block,由 &__main_block_impl_0来完成,里面传入了3个参数
- 执行block : 用到了结构体block中的FuncPtr(函数指针)
3.block结构源码
结构体里的 __main_block_impl_0
- __main_block_impl_0 : 定义一个block的时候会调用
age(_age) : 赋值 _age 赋值给age
struct __main_block_impl_0 {
struct __block_impl impl; // 里面的FuncPtr : 方法的指针
struct __main_block_desc_0* Desc;
int age;//捕获的变量
//自身的构造方法
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _age, int flags=0) : age(_age) {
impl.isa = &_NSConcreteStackBlock;
//block的类型 , 不太准,还是要以运行时所打印的类型来判断是哪种类型的block
impl.Flags = flags;//默认
impl.FuncPtr = fp;//block执行的代码块
Desc = desc;//block结构体的描述
}
};
- 从构造方法来看,block
&__main_block_impl_0
(
__main_block_func_0,
//void *fp,-- impl.FuncPtr = fp;
&__main_block_desc_0_DATA,
//struct __main_block_desc_0 *desc -- Desc = desc;
age //int _age, -- age(_age)
)
- block要执行的代码块
- _main_block_func_0
//((block)->FuncPtr)(block);
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int age = __cself->age; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_lq_l8g2c8kj16xbyccqs8h0tfyr0000gn_T_main_ab3ee1_mi_0,age);
}
- 执行block()
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
//((block)->FuncPtr)(block); //简化代码
//block->impl->FuncPtr // 过程
3. 总结
block就是一个结构体,里面有
- isa : block的类
- FuncPtr : block封装的代码块
- 局部变量 : 如果用到了局部变量,就会捕获
- 如果局部变量时对象 : block_desc里面会有copy和dispose方法