一.block简介
block即块,与函数类似,只不过是直接定义在一个函数里的,block和定义TA的那个函数共享一个范围内的东西。block其实就是个值,而且自有其相关类型,既然是个值当然就可以把块赋值给变量,然后像使用其他变量那样使用它。
二.block格式
block和c的函数格式对比如下:
第一,block变量名写在小括号里,之前加个插入符
第二,block参数列表后是等于号"=",和插入符"^"
第三,block的花括号后,有个分号
int (^blockName)(int a,int b) = ^{return a + b;}; //block
int functionName(int a,int b) {return a + b;} // c函数
三.block示例
1.block内访问函数内变量
int additional = 5;
int(^addBlock)(int a,int b) = ^(int a,int b){return a + b + additional;};
int add = addBlock(2,5); //add = 12
2.block内,如若修改函数内且block外的变量,需要在定义的变量前加 __block修饰(下面这个块来枚举数组中的元素,判断其中多少个小于2的数)。
NSArray *array = @[@0,@1,@2,@3,@4,@5];
__block NSInteger count = 0;
[array enumerateObjectsUsingBlock:^(NSNumber *number, NSUInteger idx, BOOL *stop) {
if ([number compare:@3] == NSOrderedAscending) {
count ++;
}
}];
NSLog(@"count = %ld",count); // count = 2;
在上面,传给enumerateObjectsUsingBlock:方法的参数---块,并未先赋值给局部变量,而是直接内联在函数调用里了,这就是“内联块(inline block)”的用
法。由代码中可以看出,使用了内联块,所有的业务逻辑被放在了一起,代码也更紧凑。
3.若block捕获的变量是对象类型,那么就会自动保留它,在系统释放块的时候也会将对象一起释放,由此可见,block本身也可以视为对象,block也有引用计数。
block与实例变量的关联见 P151页...
4.block分为3类,堆block,栈block,全局block,这里介绍下全局block
全局block(global block)不会捕捉任何状态(如外围的变量等),运行时也没有状态参与,块所使用的整个内存区域在编译期已经完全确定,global block可以声明在全局内存里,而不需要每次用到的时候从栈中创建,如下是个global block
void(^aBlock)() = ^{NSLog(@"这是一个global block")};
5.为block类型创建typedef
block类型写起来有些麻烦,可以使用typedef为block起个易读的别名,语句如下:
typedef int(^EOCSomeBlock)(Bool flag,int value); //声明block和定义新类型时,语法一样
而使用时,就可以直接使用新类型即可:
EOCSomeBlock block = ^(Bool flag,int value){
// Implementation
};
参照资源:
1.《Effective Objective-C 2.0》