是什么决定了解决未实现方法的过程?
据我了解,未实现的方法通过以下方式解决:
- resolveInstanceMethod:/resolveClassMethod:有机会实现该方法
- forwardingTargetForSelector:有机会转发到委托
- forwardInspiration:有机会处理该方法,因为它认为合适。
这个三步过程在哪里定义的?我想自己处理它,因为 NSInspiration 可能对于我的需求来说太重量级了。我浏览了运行时源代码,但看不到任何东西。
看起来旧的运行时会在接收器上调用forward:args:来执行此操作,但这似乎已经从新的运行时中消失了。我猜测该流程必须由框架而不是运行时定义,因为如果运行时依赖于 Cocoa 以至于需要 NSInitation 来处理消息,那就很奇怪了。是否可能是在 NSObject / NSProxy 上调用的未记录的方法?
编辑:
看起来运行时声明但从未定义一个 C 函数,当 objc_msgSend 找不到实现时调用该函数:
id objc_msgForward(id object,SEL message,... );
我不在 Apple 工作,所以我不知道 Foundation 如何实现这一点,但至少在 Cocotron 的情况下,他们使用:
id objc_msgForward(id object,SEL message,...)
{
Class class=object->isa;
struct objc_method *method;
void *arguments=&object;
if((method=class_getInstanceMethod(class,@selector(forwardSelector:arguments:)))!=NULL)
return method->method_imp(object,@selector(forwardSelector:arguments:),message,arguments);
else
{
OBJCRaiseException("OBJCDoesNotRecognizeSelector","%c[%s %s(%d)]", class_isMetaClass(class) ? '+' : '-', class->name,sel_getName(message),message);
return nil;
}
}
添加一个 forwardSelector:arguments:
方法似乎不起作用,所以我猜这是 Cocotron 特有的。有人知道 objc_msgForward 在 Foundation 中做什么吗?
As I understand it, an unimplemented method gets resolved in the following way:
- resolveInstanceMethod: / resolveClassMethod: gets a chance to implement the method
- forwardingTargetForSelector: gets a chance to forward to a delegate
- forwardInvocation: gets a chance to handle the method as it sees fit.
Where is this three-step process defined? I'd like to handle it myself as NSInvocation might be too heavyweight for my needs. I've had a poke around the runtime source and can't really see anything.
It looks like the old runtime would call forward:args: on the receiver, to do this but that seems to have gone from the new one. I'm guessing that the process must be defined by the framework rather than the runtime, since it'd be strange if the runtime depended on Cocoa to the extent of requiring NSInvocation to handle messages. Is it maybe an undocumented method that gets called on NSObject / NSProxy?
Edit:
It looks like the runtime declares, but never defines, a C function which is called when objc_msgSend can't find an implementation:
id objc_msgForward(id object,SEL message,...);
I don't work for Apple, so I don't know how Foundation implements this, but at least in the case of Cocotron, they use:
id objc_msgForward(id object,SEL message,...)
{
Class class=object->isa;
struct objc_method *method;
void *arguments=&object;
if((method=class_getInstanceMethod(class,@selector(forwardSelector:arguments:)))!=NULL)
return method->method_imp(object,@selector(forwardSelector:arguments:),message,arguments);
else
{
OBJCRaiseException("OBJCDoesNotRecognizeSelector","%c[%s %s(%d)]", class_isMetaClass(class) ? '+' : '-', class->name,sel_getName(message),message);
return nil;
}
}
adding a forwardSelector:arguments:
method doesn't seem to work, so I'm guessing this is specific to Cocotron. Anyone know what objc_msgForward
does in Foundation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
就消息转发而言,不同平台和运行时版本之间的行为[通常略有不同]。
无论如何,不要重新发明轮子。目前有两种语言桥接器可以非常接近全保真桥接,您可以从中学到很多东西。两者都拥有专门允许此类重复使用的自由许可证。
具体来说,MacRuby 项目提供了一个位于 CoreFoundation 和 Objective-C 垃圾收集器之上的 Ruby 实现。它是可用的“最原生”的桥(因此不太可移植——不是该项目的目标)。
PyObjC 桥是 Objective-C 运行时和另一种动态 OO 语言运行时之间高保真桥的最佳示例; Python。它更便携一些,尽管非 Mac OS X 的部分可能已经有些腐烂了。
(如果我不提及 F-Script,那就太失职了;一种基于 Objective-C 构建的新语言,我相信其源代码现在/曾经可用?)
所有桥都处理方法转发、子类化和跨运行时代理,所有这些听起来都适合您的特定需求。
As far as message forwarding is concerned, the behavior is [often subtly] different across different platforms and versions of the runtime.
In any case, don't re-invent the wheel. There are two language bridges available today that do pretty close to full-fidelity bridging from which you can learn a ton. Both have liberal licenses specifically to allow for such re-use.
Specifically, the MacRuby project offers a Ruby implementation that sits on top of CoreFoundation and the Objective-C Garbage Collector. It is the "most native" bridge available (and not terribly portable as a result -- not a goal of the project).
The PyObjC bridge is the best example available of a high fidelity bridge between the Objective-C runtime and another dynamic OO language's runtime; Python. It is a bit more portable, though the non-Mac OS X bits have likely rotted somewhat.
(I would be remiss in not mentioning F-Script; a new language built on Objective-C for which, I believe, the source is/was available?)
All of the bridges deal with both method forwarding, subclassing and cross-runtime proxying, all of which sound like they are applicable to your particular needs.