Block(匿名函数)
一、语法格式
正常block格式 省略返回值 省略返回值跟参数 //语法
int (^blk)(int) = ^(int count){
return count + 1;
};
int a = blk(10);
NSLog(@"%d",a);
void(^blk2)(void) = ^{
NSLog(@"blk2");
};
blk2();
typedef int (^blk_t)(int);
blk_t blk3 = ^(int count){
return count + 1;
};
int b = blk3(10);
NSLog(@"%d",b);
二、截获自动变量值和__block修饰符
block的自动变量截获只针对block中使用的自动变量。
在初始化block结构体实例时,按照传递给构造函数对由自动变量追加的成员变量进行初始化。
总的来说,所谓的截获自动变量值意味着在执行Block语法时,Block语法表达式所使用的自动变量值就被保存到Block的结构体实例(即Block自身)中。
__block修饰的自动变量,block会生成一个结构体实例,存着自动变量的值跟指针,就能对block截获的自动变量做赋值操作。
int dmy = 256;
__block int val = 10;
void (^blk4)(void) = ^{
//Variable is not assignable (missing __block type specifier)
//dmy = 0;
//__block 修饰的变量就能在block里面赋值
val = 20;
NSLog(@"%d,%d",dmy,val);
};
blk4();
三、Block的实现
简单的block通过clang转换
四、Block的存储域
内存空间在逻辑上分为三部分:代码区,静态数据区和动态数据区,动态数据区又分为栈区跟堆区。
代码区:储存方法体的二进制代码,高级调度(作业调度)、中度调度(内存调度)、低级调度(进程调度)控制代码区执行代码的切换。
静态数据区:存储运行方法的形参,静态变量、常量,系统自动分配和回收。
栈区:存储运行方法的形参、局部变量、返回值。由系统自动分配和回收。
堆区:new一个对象的引用或地址存储在栈区,指向该对象在堆区的真实数据。
在全局区的block(NSConcreteGlobalBlock):在叙述全局变量的地方使用block,生成的block,就在全局区,block里面不使用,截取其他变量的也在全局区。
在栈区的block(NSConcreteStackBlock):除了在全局区的,其他的block都在栈区生成的。
在堆区的block(NSconcreteMallocBlock):栈区的block能复制到堆区,保证出了作用域不被释放,调用block的copy方法,arc环境下,默认都对栈区的block使用了copy方法。
五、链式编程思想
链式编程思想是将事情放在block里面操作,提供一个返回改block的方法,block里面返回self,比如下面的代码,调用Dic的key方法,返回的是个block,再调用block的方法key(),就会返回self,就能再调用key和val,block的参数就是需要操作的数据。
- (Dic *(^)(NSString *))key {
return ^Dic *(NSString *pKey) {
self.chainCurrentKey = pKey;
return self;
};
}
- (Dic *(^)(id))val {
return ^Dic *(id pVal) {
self.chainDic[self.chainCurrentKey] = pVal;
return self;
};
}
masonry就是用了链式编程思想,make.top.bottom,让代码可读性变强,masonry还有一个思想,就是把操作都写在代码块里面,实现代码高聚合,具体实现就是给UIView添加一个分类,让视图控件都能调用,添加方法,方法参数是一个block,block返回类对象,方法实现里面调用block,把类对象传进去,视图调用这个分类方法就能直接获取类对象直接链式操作。
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
self.translatesAutoresizingMaskIntoConstraints = NO;
MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
block(constraintMaker);
return [constraintMaker install];
}
//(CdntAction.clas([ButtonCom class])
// 能在编译期检查的方法
+ (CdntAction *(^)(Class))clas {
return ^CdntAction *(Class clas) {
CdntAction *act = [[CdntAction alloc] init];
act.chainCls = CLS(clas);
return act;
};
}