块看起来更像函数,可以给块传递参数,就像给函数传递参数一样。块也有返回值。与函数不同的是,块定义在函数或方法的内部,并且能够访问在函数或方法范围之内块之外的任何变量。一般来说这些变量能够访问但是并不能够改变这些变量的值。有一个特殊的块修改器(由块前面含有两个下划线的字符组成)能够修改块内变量的值。
块的其中的一个优势在于能够让系统分配给其他处理器或应用的其他线程执行。例如:
int (^gcd) (int, int) = ^(int u,int v)
{
int temp;
while (v != 0)
{
temp = u % v;
u = v;
v = temp;
}
return u;
};
块是以插入字符“^”开头为标示的,后面跟的一个括号表示块所需要的参数列表。上述代码将这个块赋给gcd,等号左边表示gcd指向一个没有参数和返回值的块指针。需要注意的是赋值语句是以分号终止。执行一个变量引用的块,与函数调用的方式一致。块的定义可以是局部的也可以是全局的。int main(int argc, const char * argv[])
{
@autoreleasepool {
int foo = 10;
void (^ printFoo) (void) =
^(void) {
NSLog(@"foo = %i",foo);
};
foo = 15;
printFoo();
}
return 0;
}
此代码的运行结果为;foo = 10
因为变量在定义块的同时已具有值了,而不是在块执行的时候。
若在块内插入改变foo值的代码,就会得到编译器提示的错误信息,代码如下:
int main(int argc, const char * argv[])
{
@autoreleasepool {
int foo = 10;
void (^ printFoo) (void) =
^(void) {
NSLog(@"foo = %i",foo);
foo = 20;
};
foo = 15;
printFoo();
}
return 0;
}
但是,如果在定义本地变量foo之前插入__block修改器,就可以在块内改变外部变量的值。代码如下:int main(int argc, const char * argv[])
{
@autoreleasepool {
__block int foo = 10;
void (^ printFoo) (void) =
^(void) {
NSLog(@"foo = %i",foo);
foo = 20;
};
foo = 15;
printFoo();
NSLog(@"%i",foo);
}
return 0;
}
运行结果:foo = 15
20
第一行显示的是调用块时foo的值,第二行验证块中能否将foo值改变为20.