初识Block


Block是什么

Block是带有自动变量的匿名函数。如字面意思,Block没有函数名,另外Block带有插入记号"^",插入记号便于查找到Block,后面跟的一个括号表示块所需要的一个参数列表。和函数一样,可以给块传递参数,并且也具有返回值。不同点在于,块定义在函数或者方法内部,并且能够访问在函数或方法范围内的任何变量。通常情况下,这些变量能够访问但不能改变其值,有一个特殊的块修改器(由块前面由两个下划线字符组成)能够修改块内变量的值。


Block的语法

Block的完整语法格式如下:
^ returnType (argument list) {expressions}
与 C 语言函数的区别:

  1. 没有函数名
  2. 带有 “^” 符号
    我们写一个完整的Block:
^ int (int x) { return x; }

也可以写省略格式的Block,比如省略返回值:

^ (int x) { return x; }

Block省略返回值类型时,如果表达式中有return语句就使用该返回值的类型,没有return语句就使用void类型。

如果没有参数也可以省略参数列表:

^ { NSLog(@"Hello World"); }

像上面这么些,其实也生成了可赋值给Block类型的值,我们可以这么接收:

int (^myBlock)(int) = ^ int (int index) { return index; }
int (^block1)(int) = myBlock;

如果每次写 block 变量的时候都这样写,那不是很麻烦吗。我们可以使用 typedef 来定义一个 block 类型:

typedef int(^MyBlock)(int);

然后就可以使用 MyBlock 这个类型来定义变量了:

MyBlock blk_t = ^ (int index) { return index; }

Block类型变量可以作为自动变量,函数参数,静态变量,全局变量使用。比如将块定义在main函数外部,就可以将它扩展到全局范围。


Block截取变量

  1. 截获自动变量:如果在 block 中使用到上文中的局部变量的话,block 会将其保存到自身的内部中,不管下文那个变量怎么变,在 block 调用的时候,用的变量值都是之前截获的那个值。比如下面代码,程序的输出结果为:10
int var = 10;
MyBlock block = ^ { NSLog(@"%d", var); };
var = 20;
block();

注意:如果在Block中修改val的值会报错!
不过不用担心,我们可以用__block修饰符来实现在变量block中修改值的需求。

__block int var = 10;
MyBlock block = ^ {
    var = 20;
    NSLog(@"%d", var);
};
block();

这样程序输出结果就为20

  1. 对于全局变量、静态全局变量、静态变量在块中可以修改。
  2. 如果修改的是Objective-C对象,例如NSArray对象,不可以对其赋值但是可以增删元素。并且同样可以通过__block修饰符进行变量修改。
  3. 不能在block中访问C语言字符数组
const char text[] = "text";
MyBlock block = ^ {
    NSLog(@"%c", text[2]);
};

这样会造成编译报错,因为block中并没有实现对C语言字符数组的截获,可以将其改成指针形式:

const char *text = "text";
MyBlock block = ^ {
    NSLog(@"%c", text[2]);
};

猜你喜欢

转载自blog.csdn.net/qq_42347755/article/details/83004839
今日推荐