Objective-c编程-Blocks概要
Blocks是c语言的扩充功能,进行概述的话就是:带有局部变量的匿名函数。所谓匿名函数就是不带有名称的函数。标准的c语言是不允许这种函数的。
int func(int count)
它声明了一个名称为func的函数,在源代码中为乐调用该函数,必须使用该函数的名称func:
int result=func(10); //如果使用函数指针来代替直接调用函数,那么似乎不用知道函数名也能够使用该函数 int result=(*funcptr)(10);
但是如果深入了解的话,这种方式还是需要知道函数名称的,其具体源代码是下面这种方式;
int (*funcptr)(int)=$func; int result=(*funcptr)(10);
而通过blocks的话,源代码中能够使用匿名函数,即不带名称的函数,那么到底“带有的局部变量”到底是什么?
在c语言函数中可能使用的变量。
局部变量,函数的参数,静态变量,静态全局变量,全局变量,其中,在函数的多次调用之间能够传递值的变量有:
静态变量,静态全局变量,全局变量。
虽然这些变量的作用域不同,但是在整个程序当中,一个变量总保持在一个内存区域,因此虽然多次调用函数,但是该变量值总能保持不变,在任何时候以任何状态调用,使用的都是同样的变量值。
c++和oc可以使用类保持变量值并且能够多次持有变量自身,他会声明持有成员变量的类,它会声明持有成员变量的类,由类生成的实例活着对象保持该成员变量的值。
blocks提供了类似由c++和oc类生成实例或对象来保持变量值的方法。
Blocks模式
Block语法,即Block表达式语法,
^void (int event){ printf("buttonId:%d event=%d\n",i,event); }
这个完整的blocks语法与c语言函数的区别仅仅只有两点:
1 没有函数名。
2 带有“^”;
Block语法:我们可以在使用下面多种方法来声明blocks:
^ 返回值类型 参数列表 表达式 这是完整的声明语法
^返回类型 参数列表 表达式
^(int count){ return count+1; }
^表达式
^{return count;}
Blocks类型变量
在block语法下,就相当于生成了可赋值的Block类型变量的值,Blocks中由Block语法生成的值也被称为"Block",
生成block类型变量的示例如下:
int (^blk)(int)//blk是这个block变量的变量名。
与前面的使用函数指针的源代码对比可知,声明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.
int 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))//原来的记述方式 //采用typedef的记述方式 void func(blk_t blk){} //原来的记述方式 int (^func()(int)); //现在的记述方式 blk_t blk;
将赋值给block类型变量中的block方法像c语言通常的函数调用那样使用,这种方法与使用函数指针类型变量调用函数的方法完全相同。
下面尽享一下对比:
int result=(*funcptr)(10); //变量blk为block类型的情况下,使用下面方式 int result=blk(10);
通过block类型变量调用block与c语言通常的函数调用没有区别,在函数参数中使用block类型变量并在函数中执行BLOCK的例子。
-(int)method:blk_t blk,rate:(int)rate{ return blk(rate); }
block类型变量可完全像c语言那样使用,因此也可以指向BLOCK类型变量的指针,即block的指针类型变量。
typedef int (^blk_t)(int); blk_t blk=^(int count){return+1}; blk_t *blkptr=&blk; (*blkptr)(10);
截获自动变量值
通过上面的说明,我们暂时理解了“带有自动变量的匿名函数”的函数,那么到底什么是“自动变量”,
block表达式基本上都是会截获保存自动变量的瞬时值,因为block表达式保存了自动变量的值,所以在执行block语法之后,即使改变了block中使用的自动变量的值也不会影响自动变量执行时候的值。
__block说明符
自动变量值截获职能保存执行block语法瞬间的值,保存之后就不能改写该值如果我们尝试去修改该值就会出现错误,如果我们想要在block语法中将赋值给block语法外声明的自动变量,需要在该自动变量上附加__block说明符,就可以实现在block内部进行赋值。附有__block说明符的自动变量可在block中进行赋值,该变量称为_block变量。
如果截获的是oc对象,调用变更该对象的方法编译的时候会出现什么情况。
int main(int argc, const char * argv[]) { @autoreleasepool { __block int val=0; void (^blk)(void)=^{ val=1; NSLog(@"%d",val);}; blk(); id array=[[NSMutableArray alloc]init]; void (^blk1)(void)=^{ id obj=[[NSObject alloc]init]; [array addObject:obj]; }; blk1(); /* void(^blk2)(void)=^{ array=[[NSMutableArray alloc]init]; };*/ //这种情况下就会出现问题 必须在前面加上__block } return 0; }
自己的理解是有没有改变指针,指向的到底是不是原始的对象,如果是原始的对象,那么就不会出现异常,如果又重新赋值给新的的话,就必须在前面加上__block.

浙公网安备 33010602011771号