Objective-C之Block概要

block是带有自动变量(局部变量)的匿名函数. 匿名函数就是没有名称的函数.

另外, “带有自动变量值的匿名函数”并不仅指block, 它还存在于其他程序设计语言, 在计算机科学中, 这个概念也被称为闭包,lambda计算等.

block语法

完整形式的block定义规则如下:

^ 返回值类型 (参数列表){表达式;}

完整形式的block语法与一般的C语言函数定义相比, 仅有亮点不同:

  • 没有函数名
  • 带有符号”^”

第一点不同是没有函数名, 因为其是匿名函数. 第二点不同是返回值类型前带有”^”(插入记号,caret).

block语法还有以下几种略写形式:

  1. 省略返回值类型, 如果表达式中有return语句就使用该返回值的类型, 如果表达式中没有return语句就使用void类型. 表达式中含有多个return语句时, 所有return语句的返回值类型必须相同.
  2. 如果不适用参数, 那么参数列表也可以省略.
  3. 返回值类型和参数类别均被省略.

block类型变量

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

int (^blk)(int);

声明block类型变量仅仅是将c语言中函数指针类型变量的”*”变为”^”. 该block变量与一般的C语言变量完全相同, 可以作为以下用途:

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

使用typedef可以简化block语法, 下面的代码声明了一个blt_t类型:

typedef int (^blk_t)(int);

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

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

截获自动变量值

block表达式截获所使用的自动变量的值, 即保存该自动变量的瞬间值. 所以在执行block语法后, 即使改写block中所使用的自动变量的值也不会影响block的执行值.

int val = 10;
void (^blk)() = ^{
     NSLog(@"val=%d",val);
 };        
 val = 2;
 blk();    //val=10

__block说明符

自动变量值截获只能保存block执行瞬间的值, 保存后就不能在block中修改该值. 如果想要在block表达式中给block外的变量赋值, 则需要给该变量附加上__block说明符.

__block int val = 10;
void (^blk)() = ^{
    val = 1;
    NSLog(@"val=%d",val);   //val=1
};