Apple在C, Objective-C,C++加上Block這個延申用法。目前只有Mac 10.6 和iOS 4有支援。Block是由一堆可执行的程式组成,也可以称做沒有名字的Function (Anonymous function)。如果是Mac 10.6 或 iOS 4.0 之前的平台可以利用 http://code.google.com/p/plblocks/ 这個project得以支援Block语法。
Apple有一个叫做GCD(Grand Central Dispach)的新功能,用在同步处理(concurrency)的环境下有更好的效率,是苹果为多核多线程编程出现的解决方案。Block语法产生的动机就是來自于GCD,用Block包好一个工作量交给GCD,GCD有一个宏观的视野可以来分配CPU,GPU,Memory。
Block的实际行为和Function很像,最大的差别是在可以存取同一个Scope的变量值。Block实体形式如下:
^(传入参数列){行为主体};
Block实体开头是“^”,接着是由小括号所包起来的参数列(比如 int a, int b, int c),行为主体由大括号包起来,专有名字叫做block literal。行为主体可以用return回传值,类型会被compiler自动辨别。如果没有参数列要写成: ^(void)。
简单例子:
^(int a){return a*a;};
int result = ^(int a){return a*a;}(5); NSLog(@"%d", result);上面的方法往往太复杂,很多时候我们使用一个Block Pointer的东西来简化用法。
Block Pointer是这样定义的:
回传值(^名字)(参数列);
//声明一个square的Block Pointer,其所指向的Block有一个int输入和int输出 int (^square)(int); //将Block实体指定给square square = ^(int a){ return a*a ; }; //调用方法,感觉是是不是很像function的用法? int result = square(5); NSLog(@"%d", result);
void myFunction(int (^mySquare)(int)); //function的定义,将Block作为参数 int (^mySquare)(int) = ^(int a){return a*a;}; //定义一个mySquare的Block pointer变量 myFunction(mySquare); //把mySquare作为myFunction的参数Block需要注意的知识点
1、可以读取和Block pointer同一个Scope的变量值:
{ int outA = 8; int (^myPtr)(int) = ^(int a){ return outA + a;}; //block里面可以读取同一类型的outA的值 int result = myPtr(3); // result is 11 NSLog(@"result=%d", result); }2.Block块体里用的scope定义的变量
对于基本类型,这里copy的值是变量的值,不会变。如果它是一个记忆体的位置(地址),换句话说,就是这个变量是个指针的话,它的值是可以在block里被改变的。
3.读取static变量的值
{ static int outA = 8; int (^myPtr)(int) = ^(int a){return outA + a;}; outA = 5; int result = myPtr(3); //result的值是8,因为outA是static类型的变量 NSLog(@"result=%d", result); }
4、Block Variable类型的变量
在某个变量前面如果加上修饰字“__block”的话(注意,block前面有两个下划线),这个变量就称作block variable。
那么在block里面就可以任意修改此变量的值,如下代码:
{ __block int num = 5; int (^myPtr)(int) = ^(int a){return num++;}; int (^myPtr2)(int) = ^(int a){return num++;}; int result = myPtr(0); //result的值为5,num的值为6 result = myPtr2(0); //result的值为6,num的值为7 NSLog(@"result=%d", result); }
可以通过通过typedef定义一个区块
typedef void (^SVHTTPRequestCompletionHandler)(id response, NSHTTPURLResponse *urlResponse, NSError *error);
可以执行区块
if(block){
block(response,urlResponse,error);
}