block
从表面看相当于一个带有自动变量的匿名函数
因为block
可以传入参数有并且有返回值
在block
里还能获取到外部的变量
但是默认block
是不能修改局部变量的值
而且block
捕获的是变量的瞬时的值
但是block
可以修改静态变量、静态全局变量和全局变量
如果想要修改局部变量的值
需要在局部变量前面加一个__block
block
只会捕获用到的变量
用不到的是不会捕获的
但是本质上是一个对象
因为还有一个isa
的指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr;//指向调用函数的地址 };
struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc;//block描述信息 // 构造函数(类似于OC的init方法),返回结构体对象 __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } };
// 封装了block执行逻辑的函数 static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_c60393_mi_0); }
static struct __main_block_desc_0 { _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[]) { /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; // 定义block变量 void (*block)(void) = &__main_block_impl_0( __main_block_func_0, &__main_block_desc_0_DATA );
// 执行block内部的代码 block->FuncPtr(block); } return 0; }
|
而且block可以作为一个参数也可以作为一个返回值还能当属性
block分三种
第一种NSGlobalBlock
NSGlobalBlock
是位于全局区的block
,它是设置在程序的数据区域(.data
区)中
没有用到外界变量或只用到全局变量、静态变量的block为全局block
生命周期从创建到应用程序结束
第二种NSStackBlock
NSStackBlock
是位于栈区是位于栈区,超出变量作用域,栈上的 block
以及__block
变量都被销毁
用到局部变量、成员属性、变量的block为栈block
生命周期系统控制
函数返回即销毁
第三种NSMallocBlock
NSMallocBlock
是位于堆区,在变量作用域结束时不受影响
有强指针引用或copy修饰的成员属性引用的block会被复制一份到堆中成为堆block
没有强指针引用即销毁
生命周期由程序员控制