Block 的语法
一直以来还是有不少人不满block语法,甚至有人成立了一个叫做fuckingblocksyntax.com的网站。这个网站的网域名称不怎么优雅,不过里头倒是清楚整理了我们应该如何定义block。
将block 宣告成变数(local variable)的语法是:
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
定义成Objective-C property 的语法是:
@property (nonatomic, copy, nullability) returnType (^blockName)(parameterTypes);
定义成method 的参数(method parameter)的语法是:
- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;
在执行某个需要传入block 当做参数的method 的时候,则是用这以下方式调用。这也是绝大多数用block 当做callback 的处理方式:
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
把一种block 定义成typedef:
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
Block 也可以当成C function 的参数或是回传结果的类型,但是,在这种状况下,我们不能够直接使用returnType (^)(parameterTypes) 这种语法,必须要先定义成typedef 才行。也就是说,这样会被当成不合法:
(void (^)(void)) test((void (^)(void)) block) {
return block;
}
但可以写成这样:
typedef void (^TestBlock)(void);
TestBlock test(TestBlock block) {
return block;
}
虽然C function 的参数不能够使用returnType (^)(parameterTypes) 语法,但是一个block 倒是可以使用这种语法撰写输入与回传值的类型,但其实在这种状况下,还是比较建议使用typedef 定义。比方说,我们现在要定义一个block,这个block 会回传另外一个类型为int(^)(void) 的block,就会写成这样:
int (^(^counter_maker)(void))(void) = ^ {
__block int x = 0;
return ^ {
return ++x;
};
};
可读性实在非常差。不如写成这样:
typedef int (^CounterMakerBlock)(void);
CounterMakerBlock (^counter_maker)(void) = ^ {
__block int x = 0;
return ^ {
return ++x;
};
};