第二章 Blocks
2.1 Blocks摘要
Blocks是C语言的扩充功能,是带有自动变量(局部变量)的匿名函数。
Blocks保存自动变量的值.
Blocks不是Objective-c独有的概念,在其他语言中(如Smalltalk或Ruby)也有对应的概念。
2.2.1 Block语法
^ 返回值类型 参数列表 表达式
返回值类型可以省略
^ 参数列表 表达式
参数列表也可以省略
^ 表达式
2.2.2 Block类型变量
可将Block语法赋值给声明为Block类型的变量中。如:
int (^aBlock)(int)=^(int count){
return count+1;
};
也可以由Block类型变量向Block类型变量赋值,如
int(^bBlock)(int)=aBlock;
Block类型变量可作为函数参数,如
void func(int (^block)(int)){
}
Block类型变量作为函数返回值:
int (^func())(int){
return ^(int count){
return count+1;};
}
Block定义与函数指针定义类似,对比c语言中函数指针作为函数返回值理解:
指向函数的指针:可以仿照上边基本数据类型的定义
例如:void (*p)() =
function; (funciton是某个定义好的函数)
格式:函数类型 *指针变量名 = 函数名;
说明:由于p指针是指向函数的,所以(*p)()中的红色小括号必须有,因为函数本身是要参数的,即使没有参数也要写();
如果p指向的函数有参数:int (*pp)(int, int) = sum;
调用指向函数的指针:
无参:p();
有参:int sum = pp(2,3);
block的定义和使用,和指向函数的指针格式很像
例如:void (^firstBlock)() = ^(){...代码...}; 说明:蓝色的小括号可以不写,有参数的时候必须写
格式:block类型 ^block名称 = ^{代码段};
有参数block:int (^multiBlock)(int, int) = ^(int a, int b){
return a * b;
};
调用block:无参:firstBlock()
有参:int result = multiBlock(2, 3);
函数指针作为函数返回值:
void (*fun1(double d))(int, char)
{
printf("%f\n",d);
return fun;
}
|
使用typedef可以使block在使用时更为简洁。
typedef int (^blk_t)(int);
我们可以对比一下:
void func(int (^block)(int)){} ——>
void func(blk_t blk){}
int (^func())(int){} ——>
blk_t func(){}
调用Block方法和调用C语言函数类似。
Block类型的变量完全可像C语言变量一样使用,因此可以使用指向Block类型变量的指针,即Block指针类型变量。
blk_t blk=^(int count){return count+1};
blk_t *blkptr=&blk;
(*blk_ptr)(10);
2.2.3 截获自动变量值
int
temp=2;
void
(^myBlk)(void)=^(){printf(“%d",temp);};
temp=100;
myBlk();
结果是 2;Block表达式截获所使用自动变量(局部变量)的值。
2.2.4 __block说明符
Block只能截获自动变量的瞬间值,并不能改变自动变量的值。想要在Block的表达式中将值赋给Block语法外声明的自动变量,需要在该变量前附加 __block说明符,该变量称为 __block变量;
__block
int
temp=2;
void
(^myBlk)()=^(){
temp+=8;
};
myBlk();
printf("----%d",temp);
2.2.5 截获的自动变量
截获自动变量的值是不能被修改的,但是截获OC对象(如NSMutableArray)时,向数组中增加元素是可以的,而直接赋值是不行的。也就是可以使用,不可以进行赋值。要进行赋值,同样需要添加__block修饰符。
在使用C语言数组时应注意,截获自动变量的方法并没有实现对C语言数组的截获。如下面代码:
const
char
text[]="zyb";
void(^blk)(void)=^{
printf("%c",text[2]);
};
会提示错误:Cannot refer to declaration with an array type inside block。可以使用指针解决该问题:
const
char
*text="zyb";
void(^blk)(void)=^{
printf("%c",text[2]);
};