Block(匿名函数)

2019-11-22  本文已影响0人  廖小凡

一、语法格式

正常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;
    };
}
上一篇下一篇

猜你喜欢

热点阅读