这是这个问题的扩展:
Is it possible to create a category of the “Block” object in Objective-C.
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以对块进行评估?
解决方法
Implies that it is possible to somehow cast self to a block variable
像这样:
- (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,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; }