Block笔记(一)

2018-10-19  本文已影响0人  MichealXXX
什么是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的相关特性将对后续的学习有很大的帮助。

上一篇下一篇

猜你喜欢

热点阅读