Objective c Obj-C块能否自行执行?

Objective c Obj-C块能否自行执行?,objective-c,objective-c-blocks,objective-c-category,Objective C,Objective C Blocks,Objective C Category,这是此queston的扩展: 基本上,虽然似乎可以通过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

这是此queston的扩展:

基本上,虽然似乎可以通过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以使块进行计算?

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

NSBlock* b = ^() { /* do stuff */ };
[b invoke];
请注意,这是一个私有的、未记录的方法

意味着可以以某种方式将self强制转换为块变量

像这样:

- (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;
}
#导入
#进口
@接口Foo:NSObject
-(无效)多福;
@结束
@执行Foo
-(无效)多福{
//假设块接收到一个int,返回一个int,
//并将自身强制转换为相应的块类型
int(^selfBlock)(int)=(int(^)(int))self;
//调用自身并打印返回值
printf(“在doFoo中:%d\n”,selfBlock(42));
}
@结束
内部主(空){
[NSAutoreleasePool new];
//根据戴夫的回答
方法m=class_getInstanceMethod([Foo class],@selector(doFoo));
IMP doFoo=方法(m);
const char*type=method\u getTypeEncoding(m);
nsblock类=NSClassFromString(@“nsblock”);
class_addMethod(nsblock,@selector(doFoo),doFoo,type);
//接收int的块返回int
int(^doubler)(int)=^int(intsomenumber){返回someNumber+someNumber;};
//调用category方法,该方法依次调用自身(块)
[双打多福];
返回0;
}

这就是我一直在寻找的方法。当然,我想我在这里做的一切都是危险的,因为NSBlock本身是私有的,并且可能会更改;而不是[块调用];伟大的运行时显式动态方法是否需要添加代码?或者这也可以通过类别来完成吗?@don正如您在链接问题的答案中所解释的,我认为不可能使用类别,因为编译器在解析类别时需要原始接口声明。是的,您可以。你可以在这里面找到更多(已经开始了),我不知道这是如何解决这个问题的。答案似乎集中在如何从块定义中调用块。我说的是从块对象本身计算块。更具体地说,我希望通过这项技术能够将方法添加到块中(在NSObject或NSBlock上),以执行基于块的控制流(即[block whileTrueDo:block])。为此,我需要块在方法中重新评估自身。