这是我参与「第四届青训营」笔记创作活动的的第十一天。block是OC语言在c语言的基础上新增的数据类型之一,本篇文章旨在简单介绍一下OC语言中的block。
一、闭包
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。闭包本身是一个结构体,存储了函数入口地址和与之绑定的一系列环境,环境里面既有其本身内部定义的变量,又包含从外部捕获的变量,捕获变量的处理因实现而异。
二、block基本介绍
Objective-C中闭包的实现就是block。
Block是一个数据类型,所以可以声明这个数据类型的变量,也可以声明一个block类型的变量。block在声明时有三个组成部分:返回值,block的名称,和block传入的参数;而在给block赋值时,没有block名称这一部分,在对应的位置用返回值代替。
block变量的声明的语法:
returnType (^blockName)(parameters);
也就是 返回值类型 (^block变量的名称)(参数列表);
举例:
void (^blockName)();
这表示我声明了一个叫做blockName的block类型的变量,在这个变量中只能存储没有返回值和没有参数的代码。
int (^blockName)();
这表示我声明了一个叫做blockName的block类型的变量,在这个变量中只能存储返回值为int并且没有参数的代码。
int (^blockName)(int num);
这表示我声明了一个叫做blockName的block类型的变量,在这个变量中只能存储返回值为int并且有一个整值参数的代码。
注意:在声明block变量的时候必须要指定此变量存储的代码是否有参数和返回值,指定后就只能存储指定的代码。
初始化block变量/赋值
写一个符合block要求的代码段存储到block变量中。
书写格式:
^returnType(parameters) {
// do something;
};
也就是 ^返回值类型 (参数列表){代码;};
举例:
int (^sumBlock)(int a, int b) = ^int(int a, int b) {
return a + b;
};
这说明^int(int a, int b) {return a + b;};被赋值给了一个存储返回值为int并且有两个整值参数的代码。所以sumBlock现在存储了^int(int a, int b) {return a + b;};这个代码。
注意:赋值给block变量的代码段必须要符合block变量指定的代码。
执行存储在block变量中的代码
block变量名();
举例:
对于只有返回值没有参数的代码:
int (^myBlock)() = ^int(){
int num = 10+20;
return num;
};
int sum = myBlock();
NSLog(@"sum = %d", sum);
用一个变量接收执行存储在block变量中的代码就可以了。
对于有返回值有参数的代码:
int (^myBlock2)(int mun1, int num2) = ^int(int num1, int num2){
int num3 = num1+num2;
return num3;
};
int sum2 = myBlock2(10,20);
NSLog(@"sum2 = %d", sum);
block的简写
如果代码段没有返回值,那就可以省略void,声明block的返回值不可以省略。如果代码段没有参数,那么代码段的()可以省略。
在代码段无参数的情况下可以就只写^{ }。
int (^myBlock)() = ^{
int num = 10+20;
return num;
};
注意:block变量的声明不可以省略()。
声明block变量的时候如果有指定参数的话可以只写参数类型,省略参数名称。
举例:
int (^myBlock2)(int, int) = ^(int num1, int num2){
int num3 = num1+num2;
return num3;
};
注意:代码段的参数名称不能省略。
typedef
为了简化block声明,我们会给常用block声明定义别名,只需要在block声明的左边加上关键字typedef。typedef可以将一个长类型定义为一个短类型。也可以使用它将长的block类型定义为一个短类型。
注意:由于我们这里相当于声明了一种类型,所以block变量名在typedef时的命名一般与类的命名相同,首字母大写。
typedef returnType (^blockName)(parameters);
举例:
typedef void (^blockName)();
这说明重新定义了一个叫做blockName的无参数无返回值的类型。
思考
block类型的变量中可以存储什么样的数据?
此类型的变量中专门存储一段可以有参数和返回值的代码。但是不是所有的代码都可以存进去,在声明block变量的时候必须要指定此变量存储的代码是否有参数和返回值。指定后就只能存储指定的代码。
如果在代码段中省略了返回值,系统会如何判断返回值?
如果代码段中没有返回任何数据,那么系统会认为这个代码段是没有返回值的;如果代码段中有返回数据,返回的数据是什么类型,系统就会认为这个代码段是什么类型。
Reference
《闭包与 Objective-C block》juejin.cn/post/712344…
《Closure》www.google.com/search?q=cl…