【问题标题】:( ConformsToProtocol: && RespondsToSelector: ) vs just ( respondsToSelector: )( ConformsToProtocol: && RespondsToSelector: ) vs just ( respondsToSelector: )
【发布时间】:2013-12-05 01:08:20
【问题描述】:

当想要在委托对象上调用协议方法时,希望实现相应的协议方法,我看到开发人员首先检查

if([delegate respondsToSelector: @selector(aMethod)])
    {
        //send message;
    }

这样做不是更好甚至更安全吗? :

if([delegate conformsToProtocol:@protocol(MyProtocol)] && [delegate respondsToSelector: @selector(aMethod)])
    {
        //send message;
    }

我知道,如果协议方法定义的结构正确,那么委托中不应该有任何冲突或实现可能不是针对/来自 MyProtocol。这样的冲突是牵强的,但我遇到了一个简单声明为 -(void)willStartLogin; 的协议方法定义。我确定您已经可以开始思考并建议这种协议方法有多糟糕,例如,它可能已由委托实现以供个人/内部使用,而不是在 myDelegate 协议下使用。最好这样声明 MyProtocol 的方法: -(void)myObjectWillStartLogin:(MyObject*)myObjectInstance;以便消除任何歧义并使事情变得明显。

我希望我没有遗漏任何只需要检查 respondsToSelector 的东西: 谢谢

【问题讨论】:

  • 虽然你是正确的,不小心调用一个不适合当前委托模式的方法是有危险的,即使是一些 Cocoa 类也不检查“符合”和“响应”。这一切都取决于你想成为多么偏执。就我个人而言,我通常还有其他鳄鱼要与之搏斗。
  • 我认为大多数图书馆只使用respondsToSelector:conformsToProtocol: 应该在编译时检查
  • 我相信 Cocoa 和 Cocoa Touch 框架从不检查协议的一致性——只响应选择器。
  • 框架有时会检查协议的一致性。

标签: objective-c delegates selector protocols respondstoselector


【解决方案1】:

我不太确定你在问什么,但也许这会有所帮助:

协议是方法的集合,有些是必需的,有些是可选的。 conformsToProtocol: 回答的问题是一个对象是否声称实现了一堆方法——必需的——并且可能实现其他一些——可选的。请注意,这里是声称,而不是确实,因为未能实现所需的方法不会阻止编译(这只是一个警告)。

respondsToSelector: 回答的问题是对象是否实现了特定的方法。与conformsToProtocol: 不同,这为这种特定方法提供了明确的答案。

respondsToSelector: 的确定性是它被广泛使用的原因。

您可能认为除了方法之外检查协议会更好,因为这意味着该方法更有可能达到您的预期,如果是这样,同时使用 respondsToSelector:conformsToProtocol: 会告诉您答案寻求......有点 - 因为协议实际上只是方法名称和签名,这些方法的行为是隐含的而不是强制的(*)。

HTH。

(*如果您想强制执行合同,请查看,例如埃菲尔)

【讨论】:

  • 感谢您的回答。我知道 conformsToProtocol 不会检查协议方法是否已实现。但我的问题是:在 respondsToSelector 之上检查目标是否响应选择器不是更好,因为它符合协议。它可能会响应,因为它使用完全相同的方法符合另一个协议,或者可能只是巧合。这是 ofcoz 极不可能的,因为如果 [delegate RTS: sel]=YES 这意味着我们会这样做,例如:engine.delegate = self;这意味着我们想从引擎接收消息。希望我说得通。
【解决方案2】:

如果一个对象绝对必须符合协议,那么你应该这样声明你的对象:

id<MyProtocol> delegate;

这将为试图将不符合MyProtocol 协议的对象分配给变量/参数/属性delegate 的任何人产生编译时错误。 (他们可以使用显式强制转换来绕过警告,但这取决于他们是否明智地做到这一点。)

您仍然需要检查respondsToSelector,以防delegate 会响应选择器,因为有很多方法可能不会。 (帽子提示:@Hot Licks)

【讨论】:

  • 而且绝对不可能将错误的对象类型分配给指针,对吧?
  • @HotLicks 您说得对,您仍然需要检查 respondsToSelector 以防止可能的运行时异常。
  • @godel9 完美。我最终在午餐时记得,如果委托属性不为零,这意味着我们将在某个地方设置委托,这意味着我们希望接收协议声明的消息/方法调用。正如您所指出的,如果设置为委托的对象不符合协议,则会出现警告。所以我想 respondsToSelector 可以解决问题,尽管同时检查两者也不会损害任何逻辑。
  • @godel9 您能否举例说明除运行时问题外,代表可能不会响应选择器的其他方式?
  • 这是“非正式协议”的一个很好的例子:stackoverflow.com/questions/2010058/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-31
  • 1970-01-01
相关资源
最近更新 更多