JHHK

欢迎来到我的个人网站
行者常至 为者常成

Blocks(一)

目录

Blocks概要

带有自动变量(局部变量)的匿名函数。

  • 匿名函数
  • 自动变量

Blocks模式

一、Block语法

完整形式的Block语法与一般的C语言函数定义相比,仅有两点不同。
(1)没有函数名
(2)带有“^”符号

语法格式如下:
^ 返回值类型 参数列表 表达式

^int(int a, int b){
    NSLog(@"a+b=%d",a+b);
    return a+b;
};
//block的调用
int result = ^int(int a, int b){
  NSLog(@"a+b=%d",a+b);
  return a+b;
}(4,6);

NSLog(@"result = %d",result);

//打印结果:
//a+b=10
//result = 10

省略返回值:
^ 参数列表 表达式

//block的调用
int result = ^(int a, int b){
    NSLog(@"a+b=%d",a+b);

    //如果省略返回值,那返回值类型与return后的类型一致。
    //如果没有return,则返回值类型为void
    //如果有多个return,那么所有return后的类型应该保持一致
    return a+b;
}(4,6);

NSLog(@"result = %d",result);

//打印结果:
//a+b=10
//result = 10

省略返回值、省略参数列表:
^ 表达式

//block的调用
^{
    NSLog(@"无返回值、无参调用");
}();

//打印结果
//无返回值、无参调用

二、Block类型变量

Block变量的声明方式:

//block的类型为^int(int a,int b){};
//变量名称为blkVar
int(^blkVar)(int,int)
//Block赋值给Block变量
int(^blkVar)(int,int) = ^int(int a,int b){
    NSLog(@"a+b=%d",a+b);
    return a+b;
};

//通过变量调用Block
int result = blkVar(4,6);

NSLog(@"result=%d",result);

//打印结果为:
//a+b=10
//result=10


//还可以像下面这样使用
int(^blkVar1)(int,int) = blkVar;
int(^blkVar2)(int,int);
blkVar2 = blkVar1;

在函数参数中使用Block变量

//Block作为函数的参数(C语言形式)
void blockTest(int(^blkVar)(int,int)){
    if (blkVar) {
        int result = blkVar(4,6);
        NSLog(@"result = %d",result);
    }
}

//Block作为函数的参数(OC语言形式)
-(void)blockTest:(int(^)(int,int))blkVar{
    if (blkVar) {
        int result = blkVar(4,6);
        NSLog(@"result = %d",result);
    }
}

//函数调用(C语言形式)
blockTest(^int(int a, int b) {
    NSLog(@"a+b=%d",a+b);
    return a+b;
});

//函数调用(OC语言形式)
[self blockTest:^int(int a, int b) {
    NSLog(@"a+b=%d",a+b);
    return a+b;
}];

在函数返回值中使用Block变量

//C语言实现
int(^blockTest(int param))(int,int){
    
    printf("param=%d\n",param);
    
    return ^int(int a,int b){
        printf("a+b=%d\n",a+b);
        return a+b;
    };
}


//OC语言实现
-(int(^)(int,int))blockTest2:(int)param{
    NSLog(@"param=%d",param);

    return ^int(int a,int b){
        
        NSLog(@"a+b=%d",a+b);
        return a+b;
    };
}


//C语言调用
int(^blk)(int,int) = blockTest(3);
int result = blk(4,6);
NSLog(@"result=%d",result);
//打印结果
//param=3
//a+b=10


//OC语言调用
int(^blk1)(int,int) = [self blockTest2:3];
int result1 = blk1(4,6);
NSLog(@"result1=%d",result1);

//打印结果
//param=3
//a+b=10
//result1=10

为了简化Block的使用,可使用typedef定义block的类型

typedef int(^blkVar)(int,int);


blkVar blockTest(int param){
    
    printf("param=%d\n",param);
    
    return ^int(int a,int b){
        printf("a+b=%d\n",a+b);
        return a+b;
    };
}

-(blkVar)blockTest2:(int)param{
    NSLog(@"param=%d",param);

    return ^int(int a,int b){
        
        NSLog(@"a+b=%d",a+b);
        return a+b;
    };
}


blkVar blk = blockTest(3);
int result = blk(4,6);
NSLog(@"result=%d",result);
//打印结果
//param=3
//a+b=10


blkVar blk1 = [self blockTest2:3];
NSLog(@"[lilog]:blk1=%@",blk1);
NSLog(@"[lilog]:&blk1=%p",&blk1);


int result1 = blk1(4,6);
NSLog(@"result1=%d",result1);

//打印结果
//param=3
//a+b=10
//result1=10

三、截获自动变量值

//初始值
int val = 10;
const char * fmt = "val = %d\n";

//变量捕获
void(^blk)(void) = ^{
    printf(fmt,val);
};


//修改后的的值
val = 2;
fmt = "These values were changed.val = %d\n";

//调用
blk();

//打印结果为val = 10

四、__block说明符

__block int val = 10;

void(^blk)(void) = ^{
    //如果没有__block修饰 打印值为10;
    //val = 11 in block
    printf("val = %d in block\n",val);

    //若没有__block修饰,不允许在block内部修改值。编译器报错
    val = 1;
};

val = 11;

//调用
blk();

//val = 1
printf("val = %d\n",val);

五、截获的自动变量

如果将值赋值给Block中截获的自动变量,就会产生编译错误。

//__block NSMutableArray * array = [[NSMutableArray alloc] init];
NSMutableArray * array = [[NSMutableArray alloc] init];

void(^blk)(void) = ^{
    //改变捕获的变量,报错,
    //如果想消除错误外部声明array时,使用__block
    array = [[NSMutableArray alloc] init];
};


NSMutableArray * array1 = [[NSMutableArray alloc] init];

void(^blk1)(void) = ^{
    NSObject * obj = [[NSObject alloc] init];
    //并没有改变array变量,所以不会报错。
    [array1 addObject:obj];
};

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.