在运行时动态修改块

时间:2012-06-24 23:57:16

标签: objective-c objective-c-blocks objective-c-runtime

我正在尝试为objective-c类创建一个好的基于块的初始化器。我在超类中声明它,我希望它在所有子类中都有用。

现在我有:

+ (id)createWithBlock:(void (^) (id newObject))creationBlock {
    id newObject = [self object];    
    creationBlock(newObject);
    return newObject;
}

可以使用(在子类中):

Record *newRecord = [Record createWithBlock:^(id newObject) {
    Record *newRecord = (Record *)newObject;
    newRecord.name = @"Ginger";
    newRecord.type = @"Rhizome";
}];

现在没关系,但是我希望能有所收获。理想情况下它看起来像:

Record *newRecord = [Record createWithBlock:^{
    name = @"Ginger";
    type = @"Rhizome";
}];

但这似乎有点雄心勃勃。我也没关系:

Record *newRecord = [Record createWithBlock:^(Record *newRecord) {
    newRecord.name = @"Ginger";
    newRecord.type = @"Rhizome";
}];

这最后一个版本很难,因为看起来clang会对块进行一些编译时类型检查。以上不会使用createWithBlock的定义进行编译:我在上面,因为:incompatible block pointer types initializing 'void (^)(struct Record *)', expected 'void (^)(struct objc_object *)

如果没有进行强类型检查,我可以在运行时调用方法。 (或者,如果我输入我的块声明,我现在可以做到这一点吗?)

我一直在摸不着头脑,我已经阅读了几乎所有关于我能找到的块的文档,包括clang规范。如果有人有我想听的想法,这是一个开源项目,我认为这种模式将使所有Objective-c用户受益。

现在我的想法倾向于imp_implementationWithBlock()。但后来我需要根据那个中的内容“构建”一个新的IMP,并将其交换掉。可行?

1 个答案:

答案 0 :(得分:3)

您使用的是什么编译器?我相信最新版本的LLVM将接受您提供的最后一个代码示例。 (即你不应该犯错误。)

特别是,这适用于我在Xcode 4.3.3中的全新Xcode项目中使用LLVM 3.1。