在运行时将方法动态绑定到选择器

时间:2011-07-18 03:31:01

标签: objective-c metaprogramming late-binding

我想以编程方式将代码与选择器关联起来。我不清楚在Objective C中如何做到这一点。在Ruby中,我可能会覆盖method_missing。在Common Lisp中,我可能会定义一个宏。在Objective C中,我可以通过@dynamic属性获得部分方法,但我不清楚如何实现它们。

这是一个具体的例子:我想使用NSMutableDictionary来持久存储我的对象的一部分。我的类有两个处理基本功能的方法,以及一堆动态属性(@property中存在匹配@interface):

@dynamic name;
@dynamic age;
@dynamic favoriteColor;
- (id)accessor:(NSString*)name {
    return [[self dict] objectForKey:name];
}
- (void)mutator:(NSString*)name value:(id)value{
    [[self dict] setObject:value forKey:name];
    [[self dict] writeToFile:[self filename] atomically:YES];
}

现在我正在寻找一种方法来翻译像

这样的电话
[myInstance setName:@"iter"];

[self mutator:@"name" value@"iter"];

我想知道在ObjC中是否有一种惯用的方式。

3 个答案:

答案 0 :(得分:2)

在Objective-C中,这不是一个惯用的事情,并且肯定没有像Lisp宏那样可用。但是,NSObject和运行时提供了三个可能的点来拦截和处理引用其他方法的消息。按照运行时使用的顺序:resolveInstanceMethod:forwardInvocation:doesNotRespondToSelector:。每个文档都说明了它们的用法并给出了一些例子。

第一个要求你实际写出和add一个方法,这似乎不会达到你想要的动态状态。默认情况下,last引发异常并且不提供任何返回值。几乎可以肯定,forwardInvocation是您想要研究的内容。它允许您的对象请求另一个对象来处理方法调用,包括传递的参数;应该可以让你的对象以至少让你接近你想要的方式处理调用本身。

此外,运行时编程指南的"Message Forwarding"章节提供了一些与您的要求类似的任务示例。

答案 1 :(得分:1)

如果某个对象没有您调用的方法,则可以覆盖forwardInvocation以将方法调用委托给另一个对象。

答案 2 :(得分:0)

您可以使用Objective-C runtime functionsresolveInstanceMethod:resolveInstanceMethod:文档中有一个简短示例。