这是此问题的扩展: Is it possible to create a category of the "Block" object in Objective-C
基本上虽然似乎可以通过NSObject或NSBlock在块上创建类别,但我无法理解块如何能够自我评估。上一个问题答案中给出的例子:
- (void) doFoo {
//do something awesome with self, a block
//however, you can't do "self()".
//You'll have to cast it to a block-type variable and use that
}
意味着有可能以某种方式将self转换为块变量,但是如何执行块本身呢?例如,假设我在NSBlock上做了一个类别,并在方法中做了:
NSBlock* selfAsBlock = (NSBlock*)self;
是否有任何消息可以发送给selfAsBlock以对块进行评估?
答案 0 :(得分:7)
意味着可以以某种方式将自我转换为块变量
像这样:
- (void)doFoo {
// Assume the block receives an int, returns an int,
// and cast self to the corresponding block type
int (^selfBlock)(int) = (int (^)(int))self;
// Call itself and print the return value
printf("in doFoo: %d\n", selfBlock(42));
}
请注意(在大多数情况下)您需要修复块签名,以便编译器能够根据目标平台ABI设置调用站点。在上面的示例中,签名是返回类型int
,类型为int
的单个参数。
一个完整的例子是:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface Foo : NSObject
- (void)doFoo;
@end
@implementation Foo
- (void)doFoo {
// Assume the block receives an int, returns an int,
// and cast self to the corresponding block type
int (^selfBlock)(int) = (int (^)(int))self;
// Call itself and print the return value
printf("in doFoo: %d\n", selfBlock(42));
}
@end
int main(void) {
[NSAutoreleasePool new];
// From Dave's answer
Method m = class_getInstanceMethod([Foo class], @selector(doFoo));
IMP doFoo = method_getImplementation(m);
const char *type = method_getTypeEncoding(m);
Class nsblock = NSClassFromString(@"NSBlock");
class_addMethod(nsblock, @selector(doFoo), doFoo, type);
// A block that receives an int, returns an int
int (^doubler)(int) = ^int(int someNumber){ return someNumber + someNumber; };
// Call the category method which in turn calls itself (the block)
[doubler doFoo];
return 0;
}
答案 1 :(得分:4)
NSBlock
有invoke
方法可用于调用块。
NSBlock* b = ^() { /* do stuff */ };
[b invoke];
请注意,这是一种私有的,未记录的方法。