blockC 语言的扩充功能,本质上是一个 OC 对象,它内部也有 isa 指针,block 是封装了函数调用以及函数调用环境的 OC 对象。下面就来一步步的探索它的由来和使用方法。

block由来

先来看看 C 语言中标准的函数,如下:

1
int func(int count);

它声明了名称为 func 的函数。下面看看怎么调用的

1
int result = func(10);

如果你知道函数指针,那么应该熟悉下面这个式子,它不用知道函数名也能够使用函数。

1
int result = (*funcptr)(10);

但是,实际上仍然需要知道函数的名称。在赋值函数指针时还是需要知道函数名称的,如下:

1
int *funcptr(int) = &func;

为什么需要函数指针呢?
函数指针是为了获取函数的地址方便将函数作为参数时的调用.
为什么会出现匿名函数?
是为了代替函数指针,简化函数的书写。
block 可以真正的实现不需要函数名称的函数,方便了函数的调用。

完整的 block 语法是如下形式:
block 的声明格式:

1
2
3
4
返回值类型 (^blockName)(参数列表);
// block的声明
int (^sumblock)(int arg1, int arg2);
void (^blockName)(int arg1, int arg2)

block 的定义格式

1
2
返回值类型 (^block变量名)(形参列表) = ^(形参列表) {
};

声明并使用 block
开发者使用 ^ 操作符声明 block 变量,^ 表示是一个 block 的开始。blockbody 体在 { } 之内。例如:

1
2
3
4
int multiplier = 7;
int (^myblock)(int) = ^(int num) {
return num * multiplier;
};

image.png

block 可以使用“在其定义作用范围内的”变量;如果你声明了一个 block变量,可以像函数一样使用它。

block的用法

无参数无返回值的 block

1
2
3
4
void (^blockName)() = ^{
NSLog(@"无参数,无返回值的block");
};
blockName();

有参数无返回值的 block

1
2
3
4
void (^blockName)(int a, int b) = ^(int a, int b) {
NSLog(@"%d + %d = %d",a,b,a+b);
};
blockName(10,10);

有参数有返回值的 block

1
2
3
4
5
int (^sumblock)(int a, int b) = ^(int a, int b) {
return a + b;
};
int sum = sumblock(10,10);
NSLog(@"sum = %d",sum);

block 结合 typedef 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef int (^sumblock)(int, int);

interface ViewController ()
property (nonatomic, copy, nonnull) sumblock sumblock;
@end

@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.sumblock = ^(int a, int b) {
return a + b;
};
NSLog(@"sum = %d",self.sumblock(10,10));
}

block 作为函数参数
block 作为 C 函数参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1.定义一个形参为block的C函数
void useblockForC(int(^ablock)(int, int)) {
NSLog(@"result = %d", ablock(300,200));
}

// 2.声明并赋值定义一个block变量
int(^addblock)(int, int) = ^(int x, int y) {
return x+y;
};

// 3.以block作为函数参数,把block像对象一样传递
useblockForC(addblock);

// 将第2点和第3点合并一起,以内联定义的block作为函数参数
useblockForC(^(int x, int y) {
return x+y;
});

block 作为 OC 函数参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 1.定义一个形参为block的OC函数
- (void)useblockForOC:(int(^)(int, int))ablock
{
NSLog(@"result = %d", ablock(300,200));
}

// 2.声明并赋值定义一个block变量
int(^addblock)(int, int) = ^(int x, int y) {
return x+y;
};

// 3.以block作为函数参数,把block像对象一样传递
[self useblockForOC:addblock];

// 将第2点和第3点合并一起,以内联定义的block作为函数参数
[self useblockForOC:^(int x, int y) {
return x+y;
}];