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
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)
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With