2011-09-06 51 views
7

这是这个queston的延伸: Is it possible to create a category of the "Block" object in Objective-CObj-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 
} 

意味着它是可能以某种方式投自我块变量,但如何将一个执行块本身?例如,说我做了一个类别上NSBlock和方法都:

NSBlock* selfAsBlock = (NSBlock*)self; 

有没有我可以向selfAsBlock有块评估的任何消息?

+0

当然可以。你可以在这里找到更多(已经在SO)http://stackoverflow.com/questions/4824613/is-there-a-self-pointer-for-blocks –

+0

我不明白如何解决这个问题。这个答案似乎集中在如何从自己的块定义中调用块。我正在讨论从块对象本身评估块。只是为了更具体一点,我希望能够通过这个方法来添加方法(NSObject或NSBlock)来实现基于块的控制流(即[Block whileTrueDo:block])。要做到这一点,我需要块在方法中重新评估自己。 – donalbain

回答

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; 
} 
+0

太好了。运行时显式动态方法是否需要添加代码?或者这也可以通过一个类别来完成? – donalbain

+1

@don正如你已经链接的问题的答案中所解释的,我认为不可能使用一个类别,因为编译器在解析类别时需要原始接口声明。 – 2011-09-06 14:14:23

4

NSBlock有一个invoke方法可用于调用该块。

NSBlock* b = ^() { /* do stuff */ }; 
[b invoke]; 

请注意,这是一个私人的,未公开的方法。

+1

这就是我正在寻找的那种方法。当然,我想我在这里所做的一切都是危险的,因为NSBlock本身是私人的,可以改变。 – donalbain

+0

如果你想调用块,你可以简单地做这个块();而不是[block invoke]; https://stackoverflow.com/a/9484268 – unmircea