block使用
Blocks:带有自动变量(局部变量)的匿名函数.
之所以能够匿名,是因为C语言函数自己为其创建了名字-->规则是其所在的函数名和该block在其所属函数中所处的顺序值
//正常的block ^int (int count){return count + 1;}; //block可以省略参数,例如省略返回值类型,则自动使用根据return的类型 ^(int count){return count + 1;}; //若不适用参数,则参数列表也可以省略 ^void(void){}; //还可以这样写 ^{};
在OC中,主要使用的是Block类型的变量
Block的可以作为参数传进block里,也可以将Block类型变量作为返回值返回,block之间可以相互赋值,
//点击事件Block typedef void(^ActionBlock)(); //带参数的Block typedef void(^CallBackBlock)(id _Nullable obj); //带参数的Block typedef void(^StatusBlock)(BOOL status); // 请求回调block typedef void(^ Success)(id _Nullable json); typedef void(^ Failure)(NSString * _Nonnull errorMSG);
直接放在.h里使用方便
Block截获自动变量值
"带有自动变量值"在block里表现为"截获自动变量值"
也就是说:Block表达式截获所使用的自动变量的值,即保存该自动变量的瞬间值.因为Block保存了自动变量的值,所以在执行block语法后,即使改写Block中使用的自动变量的值,也不会影响block执行时自动变量的值.
//输出应该是2
int value = 2; void (^block)(void) = ^{ NSLog(@"%i",value); }; value = 10; block();
Block之__block
若想在Block的表达式中将值赋给外部声明的自动变量,需要在该自动变量上附加__block,
//输出值应该为10 __block int value = 2; void (^block)(void) = ^{ value = 10; }; block(); NSLog(@"%i",value);
未添加__block的情况下:截获OC对象,调用变更对象的方法不会有问题,因为block内会截获该对象的结构体实例指针.但是不能对该对象进行赋值操作.
Block的循环引用
原因:在Block中使用强引用的对象,那么Block从栈赋值到堆的时候,该对象为Block持有,就容易引起循环引用
即对象持有block,block又持有对象.死循环
__weak 与 __block的区别
__block在ARC与MRC下都可以使用,可以对对象及基本数据类型进行赋值,修改操作
__weak在ARC下可用,只能修饰对象,不能修饰基本数据类型
__block修饰的对象可以在block中重新赋值,__weak修饰的则不可以
Block修饰符
Block使用copy修饰,因为block默认是在栈区,栈区的特点是随时都可能释放,一旦释放,则调用的就是空指针,copy操作会将其拷贝到堆区,这样的话其生命周期就是随当前对象的生命周期终止才终止,对象不销毁就可以调用