所以我正在寻找into message forwarding并运行一些单元测试,当我遇到一些不足的资源,包括苹果自己的使用forwardInvocation:
的文档品牌,据我所知,methodSignatureForSelector:
methodSignatureForSelector:
工作。
现在我得到一般的想法,forwardInvocation:
需要查看您尝试转发邮件的对象是否具有匹配的方法名称和参数,以便它可以调用methodSignatureForSelector:
我的问题是为什么在苹果文档中它会调用超类的- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
signature = [surrogate methodSignatureForSelector:selector];
}
return signature;
}
实现,如此...
[super methodSignatureForSelector:selector];
对我来说,这看起来像是在说“如果我继承的类没有办法处理这个方法,请检查代理对象是否有效。”
示例苹果给出的是战士在谈判方法时代替外交官。在这个例子中,我不明白你为什么要检查战士或其中任何一个父母是否有适当的方法签名转发。因此,这让我相信它存在另一个原因,一个我无法想到的原因,有人可以给我一个例子或帮助澄清我可能会忽略这一点吗?
TL; DR
为什么我需要mysql> select DATE_SUB(NOW(),INTERVAL 30 DAY);
+---------------------------------+
| DATE_SUB(NOW(),INTERVAL 30 DAY) |
+---------------------------------+
| 2015-06-27 01:51:47 |
+---------------------------------+
?
答案 0 :(得分:4)
你是对的 - 这个例子试图从超类中获取方法签名,如果不能,则向代理请求一个。在整个转发和继承部分,Apple正在指导您如何使用邮件转发 - 无论您选择倾听都取决于您:)
完整地说,我将逐步介绍文档的主要部分:
虽然转发模仿继承,但NSObject类从不混淆这两者。像respondsToSelector:和isKindOfClass这样的方法:只查看继承层次结构,而不是转发链。
实施消息转发不会立即影响respondsToSelector
和isKindOfClass
方法。如果您将negotiate
转发给代理人,如果您继承层次结构中不存在该方法,则致电[myWarrior respondsToSelector:negotiate]
将返回NO
。
如果您使用转发设置代理对象或扩展类的功能,转发机制可能应该像继承一样透明。如果您希望对象的行为就像它们真正继承了它们转发消息的对象的行为一样,那么您需要重新实现respondsToSelector:和isKindOfClass:方法来包含转发算法。
关键字可能是 - 所以Apple会给你一个推荐。 Apple声明,如果您希望myWarrior对象在上面的示例中返回YES
,因为您将negotiate
转发给代理对象,则需要覆盖respondsToSelector
方法。现在请注意,除了negotiate
之外还有其他方法可以调用,可能在代理中您不希望返回YES
。例如,Diplomat类可能有havePeaceCelebration
方法。当Warrior类发送此消息时,您可能没有实现将消息转发到Diplomat类(因为Warriors没有和平庆祝活动),因此您将要返回NO
。
此外,父类可能没有Warrior类中的chooseWeapon
方法。如果你打电话给[myWarrior respondsToSelector:chooseWeapon]
,你绝对想要检查超类是否对它做出反应,因为代理人(作为外交官)没有。
最后,父类和代理可能都会响应选择器。 Apple似乎建议父类应该胜出 - 战士首先是战士,而某些方法的外交官,只有你强迫它。你最终如何实现它取决于你。
除了respondsToSelector:和isKindOfClass:之外,还有 instancesRespondToSelector:方法应该也镜像转发 算法。如果使用协议,则使用conformsToProtocol:方法 同样应该添加到列表中。同样,如果一个对象转发 它收到的任何远程消息,应该有一个版本 methodSignatureForSelector:可以返回准确的描述 最终响应转发消息的方法;对于 例如,如果某个对象能够将消息转发给其代理, 你将实现methodSignatureForSelector:如下:
关键字应该是 - 再次推荐。这是您提供的代码之前的声明。这与respondsToSelector
的推理相同,并且说该对象应该是一个好公民。 Warrior类可以处理一些远程消息,但不能处理其他消息,对于Diplomat类也是如此。如果您选择始终将其转发给代理,那么如果转发Warrior的超类可以处理的消息,则可能会造成混淆。或者更糟糕的是,它可能转发Warrior的超类可以处理的消息,但代理不能 - 可能导致异常。
答案 1 :(得分:0)
如果向未处理该消息的对象发送消息,则在宣布错误之前,运行时会向对象发送一个forwardInvocation:消息,其中NSInvocation对象作为其唯一参数 - NSInvocation对象封装原始消息和参数与它一起传递。