在运行时动态地将方法绑定到选择器
我想以编程方式将代码与选择器关联起来。我不清楚如何在 Objective C 中做到这一点。在 Ruby 中,我可能会重写 method_missing
。在 Common Lisp 中,我可能会定义一个宏。在 Objective C 中,我可以使用 @dynamic
属性来实现这一点,但我不清楚如何实际实现它们。
这是一个具体的示例:我想使用 NSMutableDictionary 来持久存储对象的部分内容。我的类有两个处理基本功能的方法,以及一堆动态属性(@interface
中存在匹配的 @property
):
@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 中是否有一种惯用的方法可以做到这一点。
I want to programmatically associate code with selectors. I am not clear on how to do that in Objective C. In Ruby, I might override method_missing
. In Common Lisp, I might define a macro. In Objective C, I can get part of the way there with @dynamic
properties, but I'm unclear on how to actually implement them.
Here's a concrete example: I want to use an NSMutableDictionary
to persistently store parts of my object. My class has two methods that handle the basic functionality, and a bunch of dynamic properties (matching @property
s exist in @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];
}
Now I am looking for a way to translate a call like
[myInstance setName:@"iter"];
into
[self mutator:@"name" value@"iter"];
I wonder if there is an idiomatic way to do that in ObjC.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这实际上并不是 Objective-C 中的惯用做法,而且当然也没有像 Lisp 宏那样可用的东西。然而,NSObject 和运行时确实为您提供了三个可能的点来拦截和处理引用不存在的方法的消息。按照运行时使用它们的顺序:
resolveInstanceMethod:
,转发调用:
和doesNotRespondToSelector:
。它们各自的文档解释了它们的用途并给出了一些示例。第一个要求您实际写出 向类中添加一个方法,这似乎不会实现您想要的动态状态。默认情况下,最后一个会引发异常并且不提供任何返回值。几乎可以肯定,
forwardInitation
就是您想要研究的内容。它允许您的对象要求另一个对象处理方法调用,包括传递的参数;您应该可以让您的对象以至少让您接近您想要的方式来处理调用本身。另外,“消息转发” 章节提供了一些与您的要求类似的任务示例。
This isn't really an idiomatic thing to do in Objective-C, and there's certainly nothing like a Lisp macro available.
NSObject
and the runtime do, however, provide three possible points for you to intercept and handle messages referring to methods that don't otherwise exist. In the order they are used by the runtime:resolveInstanceMethod:
,forwardInvocation:
anddoesNotRespondToSelector:
. The documentation for each of them explains their use and gives some examples.The first requires you to actually write out and add a method to the class, which doesn't seem like it will achieve the dynamic state of affairs you desire. The last by default raises an exception and doesn't provide for any return value. Almost certainly,
forwardInvocation
is what you want to look into. It allows your object to ask another object to handle a method call, including the passed arguments; it should be possible for you to make your object handle the call itself in a way that at least gets you close to what you're going for.Also, the "Message Forwarding" chapter of the Runtime Programming Guide gives some examples of tasks similar to your requirement.
如果一个对象没有您调用的方法,您可以重写
forwardInvocau
以将方法调用委托给另一个对象。If an object does not have the method that you have called on it you can override
forwardInvocation
to delegate the method call to another object.您可以使用 Objective-C 运行时函数< /a> 和
resolveInstanceMethod:
。resolveInstanceMethod:
文档中有一个简短的示例。You can use the Objective-C runtime functions along with
resolveInstanceMethod:
. There's a short example in theresolveInstanceMethod:
docs.