- Block原理
- Block自动截获局部变量
Block原理
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { void (^blk)(void) = ^{ printf("Block "); }; blk(); return 0; }
clang -rewrite-objc main.m //执行命令生成main.cpp
主要代码摘要如下:
// __block_impl struct __block_impl { void *isa; int Flags; // 标记 int Reserved; // 今后版本升级所需要的区域 void *FuncPtr;// 要调用的函数指针 }; // __main_block_impl_0即Block的结构体 struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; // 构造函数 __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) { impl.isa = &_NSConcreteStackBlock; // _NSConcreteStackBlock相当于class_t结构体实例,联想OC对象中的isa指针的功能保持该对象对应的类的结构体,由此可见Block其实就是OC对象 impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; // __main_block_func_0 static void __main_block_func_0(struct __main_block_impl_0 *__cself) { printf("Block "); } // __main_block_desc_0 static struct __main_block_desc_0 { size_t reserved; // 今后升级所需要的区域 size_t Block_size;// block的大小 } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)}; int main(int argc, const char * argv[]) { /* 构造函数调用,去掉转换部分等价于
struct __main_block_impl_0 *tmp = __main_block_impl_0(__main_block_func_0,&__main_block_desc_0_DATA);
struct __main_block_impl_0 *blk = tmp; 栈上生成的结构体实例的指针tmp,赋值给结构体指针类型的变量blk
*/ void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA)); /*
去掉转换部分等价于
(*blk->impl.FunPtr)(blk); 使用函数指针调用函数
*/ ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); return 0; }
Block自动截获局部变量
1、什么是自动截获局部变量:在执行block语法的时候,block语法表达式所使用的局部变量被保存到block的结构体实例中(没有使用的变量不会被追加)。
2、自动截获局部变量带来的问题:自动截获局部变量仅截获局部变量的值,block中在使用局部变量之后,在block结构体实例中重写该局部变量也不会改变原来截获的自动变量的值。