Block Objects 学习笔记
Block 对象集合了面向对象编程和面向过程编程的特点。可以把Block是一种类型,可以拥有实例对象,可以用某个指针变量指向一个BLOCK对象。指向Block类型的对象的变量有变量名和类型。如下代码:
NSString * string;
其中NSString *是类型,string是变量名。只是声明的语法稍有不同,如下代码:
int (^ adder)(int a, int b);
adder是Block的变量名,其中符号^代表该变量是Block类型变量。前面的int表示该对象(adder)的返回类型是int,后面的(int a,int b)表示该对想带有两个int类型的参数。
如下代码:
^int(int x, int y){
return x + y;
};
只是创建了一个Block,返回值是int类型。通常情况下,应该将新建的block立刻赋给某个Block的变量,如下:
int (^adder)(int, int) = ^int(int x, int y){
return x + y;
};
执行Block对象时,可以像c调用函数那样调用Block变量,代码如下:
int (^adder)(int, int) = ^int(int x, int y){
return x + y;
};
int sum = adder(2, 5);
NSLog(@"%i",sum);
输出结果7
Block有一个很好的特性:它能捕获变量。
首先了解Block对象的封闭作用域:对声明了某个Block的对象方法,该方法的作用域就是这个Block的对象的封闭作用域。所以该Block可以访问该方法的所有局部变量、传入该方法的实参以及传入当前对象的实例变量。
如下代码:
@interface Test1: NSObject
@property (nonatomic, copy) int (^testBlock)(int, int);
- (void) setTestBlock: (int (^)(int, int))block;
- (int) computeWithValue:(int)value addValue:(int)value2;
@end
#import "Test1.h"
@implementation Test1
@synthesize testBlock;
- (int) computeWithValue:(int)valueaddValue:(int)value2
{
if (testBlock == nil)
{
return 0;
}
return testBlock(value, value2);
}
@end
Test1 * example = [[Test1 alloc] init];
int a = 3;
[examplesetTestBlock:^int(int x, int y){
int sum;
sum = x + y;
return sum * a;
}];
NSLog(@"%d",[example computeWithValue:8 addValue:4]);
输出为36
当某个Block访问了一个在该Block之前声明的变量时,就可以说该Block捕获了这个变量。
“捕获变量”的要点:一旦某个Block对象捕获了某个变量的值,那么无论执行该Block对象多少次,被捕获的值也不会发生改变。并且被捕获的变量的值在Block之后修改,Block捕获的变量的值还是之前的值。代码如下:
int a = 3;
[example setTestBlock:^int(int x, int y){
int sum;
sum = x + y;
return sum * a;
}];
a= 6;
NSLog(@"%d",[example computeWithValue:8 addValue:4]);
输出值为36
这儿简单总结关于 Block Objects 变量的特点:
1. 局部变量在 Block Objects 和 Objective-C 方法中的工作原理非常相似。
2. 对于内联Block Objects,局部变脸不仅包含Block内部定义的变量,并且包含在BlockObjects执行方法中定义的变量。
3. 你不能参考self;在Objective-C类中运行的独立Block Objects,如果你需要访问self,就必须把Object作为参数传递到 BlockObject
4. 只有当 self 出现在创建 Block Object 的词法范围内,你可以在内联 Block Object 内参考 self。
5. 对于内联Block Objects,那些在BlockObject执行过程中定义的局部变量是可读写的,换句话说,对于Block Objects 自身的局部变量来说,Block Objects 有个读写存取。
6. 对于内联 Block Objects,实现 Object 的 Objective-C 方法的局部变量只能从中读取,不能写入。不过还有一个例外,如果定义它们通过 __block 存储类型定义的话,Block Object可以写入此类的变量。对此我们也会有举例。
7. 假设你有一个类NSObject的Object,并且在这个Object的执行中你使用了一个Block Object与GCD相连,那么在这个 Block Object 内部,你会有一个存储来读取那个支持你的 Block 执行的 NSObject内部的声明属性。