OC_block

242 阅读2分钟

什么是block

blockintfloat 等数据类型一样, block 也是一个数据类型,它可以用来声明一个数据变量。 block 类型专门用来存储一段代码,这段代码既可以有参数,也可以由返回值。

如何声明block变量

在声明一个 block 变量时,必须指定这个 block 变量的存储的代码段是否具有参数和返回值,并且一旦确定后不可更改。

声明 block 变量的格式是

// 返回值类型 (^block名称)(参数列表);
void (^MyBlock)(int a);
int (^MyBlock1)(int a, int b);

声明时可以省略参数的变量名,如:

int (^MyBlock2)(int, int);

如何初始化一个block变量

初始化一个block变量只需要写一段符合规则的代码段并赋值给变量即可。

代码段的格式:

/*
^返回值类型(参数列表){
    代码段;
};
*/

^int(int a){
    return a*a;
};

若一个代码段的返回值可以省略,系统会自动根据 return 的变量的类型确定返回值类型,如果没有参数可省略 (),例如:

^{
    NSLog(@"我是代码段");
}

然后将代码段赋值给 block 变量即可:

int (^MyBlock)(int a);

MyBlock = ^int(int a){
    return a*a;
};

注意:给 block 赋值时代码段必须符合要求,否则会报错。

用typedef定义block

因为声明 block 变量过于繁琐,当声明多个相同类型 block 变量时操作起来很麻烦。所以可以使用 typedef 定义 block 数据类型。

typedef void(^block)();
block b1;
block b2;

如何执行block

例如,我们用以下代码定义了一个 block 代码段

int (^MyBlock)(int a);

MyBlock = ^int(int a){
    return a*a;
};

我们只需要直接使用 block变量名(参数); 即可直接调用,例如:

MyBlock();

block内使用外部变量

block 内可以直接读取到外部的变量,但是直接对外部变量进行修改会报错,例如以下情况。

int a = 20;
__block int b = 20
void (^block)(void)=^{
    NSLog(@"%d %d",a,b);                //此处正常输出 20  20
    //a++;                              //此处对 a 进行自增会报错
    b++;                                //对 b 进行自增正常运行
}

所以如果在 block 内要修改外部的变量,需要在定义变量时加上 __block

block作为参数

既然 block 是一个数据类型,那么 block 声明的变量也可以作为参数传递。

block 变量作为函数的参数:

void test(void (^block)()){
    block();
}

调用 test 函数:

test(^{
    NSLog(@"我是block");
});

block 变量作为方法的参数:

-(void)doSomethingWithBlock:(int ^(blockName)(int a,int b));

调用 doSomethingWithBlock 方法:

[objectName doSomethingWithBlock:^(5,5){
    NSLog(@"我是block");
}];