( ConformsToProtocol: && RespondsToSelector: ) vs just ( respondsToSelector: )

4.4k views Asked by At

When wanting to call a protocol method on a delegate object that, hopefully, implements the respective protocol method, I see developers first checking

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

Is it not better or even safer to do this instead ? :

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

I know that if the protocol method definitions have been structured properly then there should never be any conflicts or implementations in the delegate that may not be intended for / come from MyProtocol. Such conflicts are far fetched but I have come across a protocol method definition simply declared as -(void)willStartLogin;. Im sure you can already start thinking and suggesting how such a protocol method is bad, it could for example have been implemented by the delegate for personal / internal use and not for use under the myDelegate protocol. It would be better to declare MyProtocol's method as so: -(void)myObjectWillStartLogin:(MyObject*)myObjectInstance; so as to get rid of any ambiguity and make things obvious.

I hope I am not missing anything that makes it only necessary to check respondsToSelector: Thank you

2

There are 2 answers

5
godel9 On BEST ANSWER

If an object absolutely must conform to a protocol, then you should declare your object this way:

id<MyProtocol> delegate;

This will generate compile-time errors for anyone trying to assign an object that doesn't conform to the MyProtocol protocol to the variable/parameter/property delegate. (They can use an explicit cast to get around the warning, but it's up to them to do that intelligently.)

You still need to check respondsToSelector, just in case delegate will respond to the selector, since there are a number of ways it might not. (Hat tip:@Hot Licks)

1
CRD On

I'm not really sure what you are asking, but maybe this will help:

A protocol is a collection of methods, some required, some optional. The question answered by conformsToProtocol: is whether an object claims to implement a bunch of methods - the required ones - and may implement some others - the optional ones. Note that it is claims to here, rather than does, as failure to implement a required method does not prevent compilation (it is just a warning).

The question answered by respondsToSelector: is whether an object implements a particular method. This provides a definitive answer for this particular method, unlike conformsToProtocol:.

The definitive nature of respondsToSelector: is why it is commonly used.

You may be thinking that checking for the protocol in addition to the method is better as it implies a stronger likelihood that the method does what you expect, and if so using both respondsToSelector: and conformsToProtocol: tells you the answer you seek... sort of - as protocols really are just method names and signatures, the behaviour of those methods being implied rather than enforced(*).

HTH.

(* if you want enforced contracts look at, for exmaple, Eiffel)