目录
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];
};
行者常至,为者常成!