Objective c (ConformsToProtocol:&;RespondsToSelector:)与just(RespondsToSelector:)

Objective c (ConformsToProtocol:&;RespondsToSelector:)与just(RespondsToSelector:),objective-c,delegates,selector,protocols,respondstoselector,Objective C,Delegates,Selector,Protocols,Respondstoselector,当想要在委托对象上调用一个协议方法,希望实现相应的协议方法时,我看到开发人员首先检查 if([delegate respondsToSelector: @selector(aMethod)]) { //send message; } 这样做不是更好,甚至更安全吗 if([delegate conformsToProtocol:@protocol(MyProtocol)] && [delegate respondsToSelector: @sele

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

if([delegate respondsToSelector: @selector(aMethod)])
    {
        //send message;
    }
这样做不是更好,甚至更安全吗

if([delegate conformsToProtocol:@protocol(MyProtocol)] && [delegate respondsToSelector: @selector(aMethod)])
    {
        //send message;
    }
我知道,如果协议方法定义的结构正确,那么委托中永远不会有任何冲突或实现,这些冲突或实现可能不是针对MyProtocol的,也可能不是来自MyProtocol的。这样的冲突很牵强,但我遇到了一个协议方法定义,它简单地声明为-(void)willstartogin;。我相信你已经可以开始思考和建议这样的协议方法有多糟糕,例如,它可能是由代理实现的,用于个人/内部使用,而不是在myDelegate协议下使用。最好将MyProtocol的方法声明为:-(void)myobjectwillstartogin:(MyObject*)myObjectInstance;以消除任何歧义,使事情变得明显

我希望我没有遗漏任何只需要检查选择器响应的内容:
谢谢

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

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


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

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

协议是一组方法,有些是必需的,有些是可选的。
conformsToProtocol:
回答的问题是,一个对象是否声称要实现一系列方法(必需的方法),并且可能实现一些其他方法(可选的方法)。请注意,它在此处声明,而不是声明,因为未能实现所需的方法不会阻止编译(这只是一个警告)

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

respondsToSelector:
的明确性质就是它被普遍使用的原因

您可能会认为,除了方法之外,检查协议更好,因为它意味着该方法实现您期望的结果的可能性更大,如果是这样,则同时使用
响应选择器:
一致性协议:
告诉您所寻求的答案。。。某种程度上——因为协议实际上只是方法名和签名,这些方法的行为是隐含的,而不是强制的(*)


(*如果您想要强制契约,请查看exmaple、Eiffel)

尽管您认为存在意外调用不适用于当前委托模式的方法的危险,但即使某些Cocoa类也不会同时检查“符合”和“响应”。这完全取决于你有多偏执。就我个人而言,我通常还有其他的鳄鱼要对付。我认为大多数库只使用
respondsToSelector:
conformsToProtocol:
应该在编译时检查。我相信Cocoa和Cocoa Touch框架从不检查协议的一致性——只检查选择器的响应。框架有时检查协议的一致性。而且绝对不可能将错误的对象类型分配给指针,对吗?@HotLicks您是正确的,您仍然需要检查
respondsToSelector
,以防止可能的运行时异常。@godel9完美。我最终在午餐时想起,如果delegate属性不是nil,这意味着我们将在某个地方设置delegate,这意味着我们希望接收协议声明的消息/方法调用。正如您所指出的,如果设置为委托的对象不符合协议,则会出现警告。因此,我想respondsToSelector可以做到这一点,尽管检查两者也不会损害任何逻辑。@godel9您能否举例说明除运行时问题外,代理可能不会响应选择器的其他方式?这是一个很好的“非正式协议”示例:谢谢您的回答。我知道conformsToProtocol不检查协议方法是否已实施。但我的问题是:在respondsToSelector之上,检查目标是否响应选择器不是更好,因为它符合协议。它可能会响应,因为它使用完全相同的方法符合另一个协议,或者可能只是巧合。这是极不可能的,因为如果[delegate RTS:sel]=YES,这意味着我们会这样做,例如:engine.delegate=self;这意味着我们希望从引擎接收消息。希望我说的有道理。