Block简介:app
Block的实际行为和Function很像,最大的差异是在能够存取同一个Scope的变量值。Block实体形式以下:spa
^(传入参数列){行为主体};.net
Block实体开头是“^”,接着是由小括号所包起来的参数列(好比 int a, int b, int c),行为主体由大括号包起来,专有名字叫作block literal。行为主体能够用return回传值,类型会被compiler自动辨别。若是没有参数列要写成: ^(void)。指针
例以下面的一个例子:orm
[cpp] view plain copyblog
^(int a){return a*a;}; three
这是表明Block会回传输入值的平方值(int a 就是参数列, return a*a; 就是行为主体)。记得行为主体里最后要加“;”,由于是叙述,而整个{}最后也要加“;”,由于Block是物件实体。用法以下:ip
[cpp] view plain copyrem
int result = ^(int a){return a*a;}(5); get
NSLog(@"%d", result);
很奇怪吧?后面的小括号里面的5会被当成a的输入值,而后经由Block输出 5*5 = 25指定给result这个变量。
有没有简单一点的方法嗯?否则每次都写这么长?有。接下来介绍一个叫作Block Pointer的东西来简化咱们的写法。
Block Pointer是这样定义的:
回传值(^名字)(参数列);
好比下面的例子:
[cpp] view plain copy
//声明一个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);
是否是变的简单了?
也能够吧Block Pointer当成参数传递给一个function,好比:
[cpp] view plain copy
void myFunction(int (^mySquare)(int)); //function的定义,将Block做为参数
int (^mySquare)(int) = ^(int a){return a*a;}; //定义一个mySquare的Block pointer变量
myFunction(mySquare); //把mySquare做为myFunction的参数
上面的三行代码其实等价于下面这行代码:
[cpp] view plain copy
myFunction( ^int(int a){return a*a;} );
当其做为Object-C method的传入值的话,须要把类型写在变量前面,而后加上小括号。好比下面这种写法:
[cpp] view plain copy
-(void)objcMethod:(int(^)(int))square; //square参数的类型是int(^)(int)
存取变量
一、能够读取和Block pointer同一个Scope的变量值:
[cpp] view plain copy
{
int outA = 8;
int (^myPtr)(int) = ^(int a){ return outA + a;};
//block里面能够读取同一类型的outA的值
int result = myPtr(3); // result is 11
NSLog(@"result=%d", result);
}
下面来看一段颇有意思的代码:
[cpp] view plain copy
{
int outA = 8;
int (^myPtr)(int) = ^(int a){ return outA + a;}; //block里面能够读取同一类型的outA的值
outA = 5; //在调用myPtr以前改变outA的值
int result = myPtr(3); // result的值仍然是11,并非8
NSLog(@"result=%d", result);
}
为何result 的值仍然是11?而不是8呢?事实上,myPtr在其主体中用到的outA这个变量值的时候作了一个copy的动做,把outA的值copy下来。因此,以后outA即便换成了新的值,对于myPtr里面copy的值是没有影响的。
须要注意的是,这里copy的值是变量的值,若是它是一个记忆体的位置(地址),换句话说,就是这个变量是个指针的话,
它的值是能够在block里被改变的。以下例子:
[cpp] view plain copy
{
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
int result = ^(int a){[mutableArray removeLastObject]; return a*a;}(5);
NSLog(@"test array :%@", mutableArray);
}
本来mutableArray的值是{@"one",@"two",@"three"},在block里面被更改mutableArray后,就变成{@"one", @"two"}了。
二、直接存取static类型的变量
[cpp] view plain copy
{
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);
}
甚至能够直接在block里面修改outA的值,例以下面的写法:
[cpp] view plain copy
{
static int outA = 8;
int (^myPtr)(int) = ^(int a){ outA = 5; return outA + a;};
int result = myPtr(3); //result的值是8,由于outA是static类型的变量
NSLog(@"result=%d", result);
}
三、Block Variable类型的变量
在某个变量前面若是加上修饰字“__block”的话(注意,block前面有两个下划线),这个变量就称做block variable。
那么在block里面就能够任意修改此变量的值,以下代码:
[cpp] view plain copy
{
__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);
}
由于myPtr和myPtr2都有用到num这个block variable,最终num的值为7.未完待续。。