美文网首页
Block笔记(一)

Block笔记(一)

作者: MichealXXX | 来源:发表于2018-10-19 16:31 被阅读0次
    什么是block

    Blocks是C语言的扩充功能,可以用一句话来表示Blocks的扩充功能:带有自动变量(局部变量)匿名函数

    所谓匿名函数就是不带有名称的函数。C语言的标准不允许存在这样的函数。例如以下源码:

    int func (int count);
    

    它声明了名称为func的函数。下面的源码中为了调用函数,必须使用该函数的名称func

    int result = func(10);
    

    如果像下面这样,使用函数指针来代替直接调用函数,那么似乎不用知道函数名也能够使用该函数。

    int result = (*funcptr)(10);
    

    但其实使用函数指针也仍需要知道函数名称。

    int (*funcptr)(int) = &func;
    int result = (*funcptr)(10);
    

    而通过Blocks,源代码中就能够使用匿名函数,即不带函数名称的函数。对于程序员来说,命名占用了很大比重,函数名,变量名,方法名,属性名,类名和框架名等都必须具备,而能够编写不带名称的函数对于程序员来说相当具有吸引力。

    现在我们知道了匿名函数的概念。那么带有自动变量值又是什么呢?我们先来回顾一下在C语言函数中可能使用的变量
    自动变量(局部变量)
    函数的参数
    静态变量(静态局部变量)
    静态全局变量
    全局变量
    其中在函数的多次调用之间能够传递值的变量有,静态变量(静态局部变量)静态全局变量全局变量

    虽然这些变量的作用域不同,但在整个程序当中,一个变量总保持在一个内存区域。因此虽然多次调用函数,但该变量值总保持不变,在任何时候以任何状态调用,使用的都是同样的变量值。

    C++和Objective-C使用类可保持变量值且能够多次持有该变量自身。它会声明持有成员变量的类,由类生成的实例对象保持该成员变量的值。但是声明并实现C++,Objective-C的类增加了代码的长度。这时我们就要用到Blocks了。Blocks提供了类似由C++和Objective-C类生成实例或对象来保持变量值的方法。

    Block语法

    完整形式的Block语法与一般的C语言函数定义相比,仅有两点不同。没有函数名,带有“^”。Block语法的BN范式如下:
    ^ 返回值类型 参数列表 表达式
    例如以下形式:

    ^int (int count) {return count + 1}
    

    Block的语法可以省略很多东西,我们可以省略其返回值,如果不使用参数,我们也可以省略其参数列表返回值类型以及参数列表均被省略的Block语法应该是最常见的记述方式。

    Block类型变量

    在Block语法下,可将Block语法赋值给声明为Block类型的变量中,即源代码中一旦使用Block语法就相当于生成了可赋值给Block类型变量的“值”。Block中由Block语法生成的值也被称为“Block”。“Block”既指源代码中的Block语法,也指由Block语法所生成的值

    int (^blk)(int) = ^int (int count) {return count + 1}
    

    在日常开发中我们会经常使用typedef来声明Block类型的变量

    typedef void (^myTestBlock)(NSString *参数1,NSString *参数2);
    

    调用

    self.myTestBlock(参数1, 参数2);
    

    取得回调

    self.myTestBlock = ^(NSString *参数1, NSString *参数2) {
    
        };
    
    截获自动变量值

    我们之前已经了解到了带有自动变量(局部变量)匿名函数中的匿名函数,那么带有自动变量值究竟是什么呢?其实它在Block中表现为“截获自动变量值”。实例如下:

    - (void)testBlock{
        int dmy = 256;
        int val = 10;
        void (^blk)(void) = ^{
            NSLog(@"%d,%d",dmy,val);
        };
        val = 2;
        blk();
    }
    

    Blocks中,Block表达式截获所使用的自动变量的值,即保持该自动变量瞬间值,所以在执行Block语法后,即使改写Block中使用的自动变量的值也不会影响Block执行时自动变量的值。

    2018-10-19 15:26:20.873463+0800 testDemo[74354:1089050] 256,10
    

    执行结果并不是改写后的值,在Block执行时这些值被保存,从而在执行块时使用,这就是自动变量值的截获。

    _ _block说明符

    实际上,自动变量值截获只能保存执行Block语法瞬间的值。保存后就不能改写该值,我们尝试改写截获的自动变量值,看看会出现什么结果。

    int main(){
        int val = 0;
        
        void (^block)(void) = ^{
            val = 1;
        };
        block();
        
        printf("block");
        
        return 0;
    }
    

    该段代码会产生编译错误。

    Variable is not assignable (missing __block type specifier)
    

    若想在Block语法的表达式中将值赋给在Block语法外声明的自动变量,需要在该自动变量上附加__block说明符。

    int main(){
        __block int val = 0;
        
        void (^block)(void) = ^{
            val = 1;
        };
        
        block();
        
        printf("val = %d\n",val);
        
        return 0;
    }
    

    执行结果:

    val = 1
    
    总结

    这一篇先讲解了一些block的概念,规范,功能以及一些用法,下一篇将着重记录Block的实现,在深究其原理前先明白block的相关特性将对后续的学习有很大的帮助。

    相关文章

      网友评论

          本文标题:Block笔记(一)

          本文链接:https://www.haomeiwen.com/subject/dfmyzftx.html