【ios学习】之七、Blocks简介

blocks
blocks是c语言的扩充,他是:带有自动变量(局部变量)的匿名函数。
这个概念叫做:闭包。如python中的lambda,在c++11中也引入了lambda;
维基百科中关于闭包:闭包Closure)是词法闭包Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
blocks的语法:
^ 返回值类型  参数列表  表达式
^ 参数列表  表达式
^ 表达式

^void (int i){ printf("%d", i);}
^(int i){printf("%d", i);}
^{printf("123");}

这里要注意,当你省略返回值类型的时候,你的表达式里return返回什么类型,那么你的返回值类型就是什么。
当你不适用参数的时候,(void) 参数列表可以省略。

在使用block的时候,我们可以声明block变量,他同c中的函数指针:
int f(int a) {
     return a;
}
int (*fa)(int) = &f;

在blocks中,block指源代码中的block语法,也指由block语法生成的值。
int (^blk)(int);

int (^blk)(int) = ^(int a){ printf("%d, a); }
int (^blk1)(int) = blk;
int (^blk2)(int);
blk2 = blk1;

void f(int (^blk)(int));   //向函数传递block

可以使用typedef:
typedef int (^blk_t)(int);

void f(int (^blk)(int))  对应: void f(blk_t blk)
int (^f()(int))  对应: blk_t f();

比较函数指针:

int (*ff(int))(int *, int);

这个有点难理解了,我们要从里往外看:

ff(int)   这里将ff声明为一个函数,它有一个int的形参。  

这个函数的返回值就是int (*)(int *, int);

这是一个指向函数的指针。我们来变一下形式:

  1. typedef int (*func)(int*, int);   
  2. func ff(int)  

这里可以看到,他们只有一个* 和一个 ^ 的区别。
他可以作为:自动变量,函数参数,静态变量,静态全局变量,全局变量使用。
block类型变量可以和c语言中其他类型变量一样使用。
如: 
typedef int (^blk_t)(int);
     blk_t blk = ^(int count){return count;};
    blk_t *blkptr = &blk;
     (*blkptr)(10);

自动变量
来说一下自动变量:
block表达式截获所使用的自动变量的值:保存该自动变量的瞬间值。
代码解释:
int val = 0;
void (^blk)(void) = ^{printf("%d", val);};
val = 3;
blk();

此时,输出的是0而不是3.

__block

自动变量值截获只能保存执行block语法瞬间的值,保存后不能改写了。 当你在block改写截获的自动变量时,会产生编译错误。
如果想要在block语法的表达式中将值付给block语法外声明的自动变量,那么需要在这个自动变量上附加__weak说明符:
__block int a = 0;
void (^blk)(void) = ^{a = 1;};
blk();

获取的自动变量
id array = [[NSMutableArray alloc]init];
void (^blk)(void) = ^{id obj = [[NSObject alloc]init];
                         [array addObject:obj];};

id array = [[NSMutableArray alloc]init];
void (^blk)(void) = ^{array = [[NSMutableArray alloc]init];};

上面两段代码第二段会出现错误,应该加上__block说明符。 因为向截获的变量array赋值会产生编译错误。但是使用截获的值是不会产生任何问题的。

const char text[] = "hello";
void (^blk)(void) = ^{printf("%c", text[2]);};

const char *text = "hello";
void (^blk)(void) = ^{printf("%c", text[2]);};
上面两段代码会出现不同的结果,第一段会报错,因为截获自动变量的方法没有实现对c数组的截获。


-----2014/3/18  Beijing

【ios学习】之七、Blocks简介,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。