Tuesday, July 05, 2011

The Reason Why an Objective-C Protocol Doesn't Implement respondsToSelector:

I've been having a lot of fun with Objective-C protocols lately. In one of the projects I'm on, I've been working to eliminate warnings from the compiler. One of those warnings is that respondsToSelector: isn't found in your delegate or data source. When working with a delegate or data source, two different naming conventions for Objective-C protocols, a typical pattern your code follows is to see if your delegate or data source actually implements a method defined in your protocol, like this:
- (void)notifyDelegateOfButtonTap
{
    if (self.delegate &&
       [self.delegate respondsToSelector:@selector(protocolSampleViewController:didTapButton:)])
    {
        [self.delegate protocolSampleViewController:self didTapButton:self.button];
    }
}
The protocol definition would typically look like this when implementing this pattern:
@protocol ProtocolSampleViewControllerDelegate
@optional
- (void)protocolSampleViewController:(ProtocolSampleViewController *)protocolSampleViewController didTapButton:(UIButton *)button;
@end
This is a typical protocol definition as code completed in Xcode 3.x, with the addition of @optional just to maintain pattern correctness for the example. In Xcode 4.x, the code completed @protocol definition template looks like this:
@protocol protocol name <NSObject>
methods
@end
As you might have guessed by now, the <NSObject> added behind the protocol name is the key. That's because it's actually the NSObject protocol that defines most of the core methods that the NSObject class implements, including respondsToSelector:

Once you make sure all your protocol definitions adopt the <NSObject> protocol, then calling respondsToSelector: on your delegate or datasource variables won't result in compiler warnings.

One more thing...you could cast your delegate or data source variable to id like this:
...
[(id)self.delegate respondsToSelector:@selector(protocolSampleViewController:didTapButton:)]
...
That is an ugly solution and doesn't help you understand another key feature of protocols, inheritance, which I plan to cover in an upcoming post.