今天总结学习一下Block。
1、声明Block对象变量
声明包括变量名和类型两个属性。如下代码:
int (^addr)(inta,int b);
这行代码声明了一个名为adder的Block变量,其指向的是Block对象应该有两个int实参,返回值也应该是int类型。变量名前的^符号代表adder是Block变量,而不是普通的指针变量。Block对象的声明语法和C函数的声明语法类似,差别是需要在变量前增加一个^前缀,并且要将这个^和变量名写在一对括号里。
2、定义Block对象
Block变量只能保存某个Block对象的地址。因为Block对象也是对象,所以需要为其分配内存空间。
创建Block对象的实例代码:
^int(int x,int y)
{
return x+y;
}
这种Block对象的定义语法称为block literal,具体的规则是^字符,后跟返回值类型,然后是包括实参的一对括号,最后是包括具体实现的一对花括号。
通常情况下,应该将新创建的Block对象立刻赋给某个Block变量(也可以将新创建的Block对象作为实参传入某个方法)。
int (^addr)(inta,int b) = ^int(int x,int y){
return x+y;
};
3、执行Block对象
int sum = adder(2,3);
NSLog(@"%d",sum);
要点:
1、声明Block变量时可以忽略实参的参数名。
2、Block对象只能指向和其类型匹配的Block对象,否则编译器也会报错。
3、Block对象是在方法(或函数)内创建的,这点有别于方法定义和函数定义。
4、Block对象可以捕获变量。Block对象也可以使用其封闭作用域内的所有变量。一旦Block对象捕获了某个变量,该变量之后的变化就不会对捕获后的变量产生任何影响。针对Block对象中的这类捕获后的变量,任何修改都是无效的。例如:int five = 5;
void(^block)(void) = ^{
five = 6;//这行代码会产生错误
};
Block对象会针对作用域内所使用的对象,保留强引用类型的引用。因此,当Block对象像某个对象发送消息,或者使用某个对象,都会导致应用保留该对象,直到释放相应的Block对象。
5、当需要修改Block对象中的某个变量,需要使用__block关键字,将相应的变量声明为“可修改”,例如:
__block int count = 0;
void (^block)(void) = ^{
count ++;
NSLog(@"Counter now at %d",counter);
};
block();/输出1
block();//输出2
如果在定义Block对象之后修改counter,相应Block对象中的counter的值也会发生变化,代码如下:
__block int count = 0;
void (^plusOne)(void) = ^{
count ++;
NSLog(@"Counter now at %d",counter);
};
counter = 25;plusOne();//输出26
6、如果某个Block对象捕获的是指向对象的指针,那么即使没有使用__block,也一样能修改该对象的属性(但是不能修改指针指向的对象)。那么用__block修饰了某个指针变量,就可以在Block中修改该指针所指向的对象。