Block 2: Block语法

Block语法

    下面详细讲解一下带有局部变量值的匿名函数Block的语法。前面按钮回调例子中使用的Block语法如下:

^(int event) {
  printf("buttonId:%d event=%d", i, event);
}

    实际上,该Block语法使用了省略方式,其完整形式如下:

^void (int event) {
  printf("buttonId:%d event=%d", i, event);
}

    如上所示,完整形式的Block语法与一般的C语言函数定义相比,仅有两点不同。

    ① 没有函数名。

    ② 带有“^”。

    第一点不同是没有函数名,因为它是匿名函数。第二点不同是返回值类型前带有“^”(插入记号,caret)记号。因为OS XiOS应用程序的源代码中将大量Block,所以插入该记号便于查找。

    Block语法如下:

^ 返回值类型 参数列表 表达式

     “返回值类型”同C语言函数的返回值类型,“参数列表”同C语言函数的参数列表,“表达式”同C语言函数中允许使用的表达式。当然与C语言函数一样,表达式中含有return语句时,其类型必须与返回值类型相同。

    例如可以写出如下形式的Block语法:

^int (int count){return count + 1;}

    虽然前面出现过省略方法,但Block语法可省略好几个项目。首先是返回值类型:

^ 返回值类型 参数列表 表达式

 省略后:

^ 参数列表 表达式

     省略返回值类型时,如果表达式中有return语句就使用该返回值的类型,如果表达式中没有return语句就使用void类型。表达式中含有多个return语句时,所有return的返回值类型必须相同。前面的源代码省略其返回值类型时如下所示:

^(int count){return count + 1;}

    该Block语法将按照return语句的类型,返回int型返回值。

    其次,如果不使用参数,参数列表也可省略。以下为不使用参数的Block语法:

^void (void){printf(“Blocks”);}

    该源代码可省略为如下形式:

^{printf(“Blocks”);}

    返回值类型以及参数列表均被省略的Block语法是大家最为熟知的方式吧。

 ^ 返回值类型 参数列表 表达式

 省略后

^ 表达式

 Block类型变量

    上面讲到Block语法单从其记述方式上来看,除了没有名称以及带有“^”以外,其他都与C语言函数定义相同。在定义C语言函数时,就可以将所定义函数的地址赋值给函数指针类型变量中。

int func(int count) {
  return count + 1;
}

 
int (*funcptr)(int) = &func;

    这样一来,函数func的地址就赋值给函数指针类型变量funcptr中了。

    同样地,在Block语法下,可将Block语法赋值给声明为Block类型的变量中。即源代码中一旦使用Block语法就相当于生成了可赋值给Block类型变量的“值”。Blocks中由Block语法生成的值也被称为“Block”。在有关Blocks的文档中,“Block”既指源代码中的Block语法,也指由Block语法所生成的值。

    声明Block类型变量的示例如下:

int (^blk)(int);

    与前面的使用函数指针的源代码对比可知,声明Block类型变量仅仅是将声明函数指针类型变量的“*”变为“^”。该Block类型变量与一般的C语言变量完全相同,可作为以下用途使用。

  •  自动变量
  •  函数参数
  •  静态变量
  •  静态全局变量
  •  全局变量

    那么,我们就试着使用Block语法将Block赋值为Block类型变量。

int (^blk)(int) = ^(int count){return count + 1;};

    由“^”开始的Block语法生成的Block被赋值赋值给变量blk中。因为与通常的变量相同,所以当然也可以由Block类型变量向Block类型变量赋值。

int (^blk1) (int) = blk;
int (^blk2)(int);
blk2 = blk1;

    在函数参数中使用Block类型变量可以向函数传递Block

void func(int (^blk)int)) {...

    在函数返回值中指定Block类型,可以将Block作为函数的返回值返回。

int (^func()(int)) {
 return ^(int count){return count + 1;};
}

    由此可知,在函数参数和返回值中使用Block类型变量时,记述方式极为复杂。这里,我们可以像使用函数指针类型时那样,使用typedef来解决该问题。

typedef int (^blk_t)(int);

    如下所示,通过使用typedef可声明“blk_t”类型变量。我们试着在以上例子中的函数参数和函数返回值部分里使用一下。

void func(int (^blk)(int)) //原来的记述方式
void func(blk_t blk)

 
int (^func()(int)) //原来的记述方式
blk_t func()

    通过使用typedef,函数定义就变得更容易理解了。

    另外,将赋值给Block类型变量中的Block方法像C语言通常的函数调用那样使用,这种方法与使用函数指针类型变量调用函数的方法几乎完全相同。变量funcptr为函数指针类型时,像下面这样调用函数指针类型变量:

int result = (*funcptr)(10);

    变量blkBlock类型的情况下,这样调用Block类型变量:

int result = blk(10);

    通过Block类型变量调用BlockC语言通常的函数调用没有区别。在函数参数中使用Block类型变量并在函数中执行Block的例子如下:

int func(blk_t blk, int rate) {
  return blk(rate);
}

     当然,在Objective-C的方法中也可使用。

- (int)methodsUsingBlock:(blk_t)blk rate:(int)rate {
  return blk(rate);
}

    Block类型变量可完全像通常的C语言变量一样使用,因此也可以使用指向Block类型变量的指针,即Block的指针类型变量。

typedef int (^blk_t) (int);
blk_t blk = ^(int count){return count + 1;};
blk_t *blkptr = &blk;
(*blkptr)(10);

    由此可知Block类型变量可像C语言中其他类型变量一样使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值