6

据我了解,未实现的方法通过以下方式解决:

  1. resolveInstanceMethod: /resolveClassMethod: 获得实现方法的机会
  2. forwardingTargetForSelector:有机会转发给委托人
  3. forwardInvocation: 有机会处理它认为合适的方法。

这个三步过程在哪里定义?我想自己处理它,因为 NSInvocation 可能对我的需求来说太重了。我已经在运行时源上戳了一下,但实际上什么也看不到。

看起来旧的运行时会在接收器上调用 forward:args: 来执行此操作,但这似乎已经从新的运行时消失了。我猜这个过程必须由框架而不是运行时定义,因为如果运行时依赖 Cocoa 到需要 NSInvocation 来处理消息的程度,那就很奇怪了。它可能是在 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_msgForwardFoundation是做什么的吗?

4

1 回答 1

6

我正在写一些有点像脚本语言的东西,它使用消息转发与objective-c 交互。目前,我正在使用 NSInvocation,但它最终可能每秒执行数千次,因此开销会很明显。但我想我也只是好奇...

就消息转发而言,行为在不同平台和运行时版本之间[通常]微妙地不同。

无论如何,不​​要重新发明轮子。今天有两种语言桥接器可以提供非常接近全保真桥接,您可以从中学到很多东西。两者都具有专门允许此类重用的自由许可证。

具体来说,MacRuby 项目提供了一个位于 CoreFoundation 和 Objective-C 垃圾收集器之上的 Ruby 实现。它是可用的“最原生”的桥接器(因此不是非常便携——不是项目的目标)。

PyObjC 桥是 Objective-C 运行时和另一种动态 OO 语言运行时之间的高保真桥的最佳示例;Python。虽然非 Mac OS X 位可能已经有些腐烂,但它更便携一些。

(如果我没有提到 F 脚本,我会失职;一种基于 Objective-C 的新语言,我相信它的源代码是/可用的?)

所有的桥都处理方法转发、子类化和跨运行时代理,所有这些听起来都适用于您的特定需求。

于 2011-01-29T18:57:37.750 回答