views:

2389

answers:

1

I have an object (a UIViewController) which may or may not conform to a protocol I've defined.

I know I can determine if the object conforms to the protocol, then safely call the method:

if([self.myViewController conformsToProtocol:@protocol(MyProtocol)]) {
    [self.myViewController protocolMethod]; // <-- warning here
}

However, XCode shows a warning:

warning 'UIViewController' may not respond to '-protocolMethod'

What's the right way to prevent this warning? I can't seem to cast self.myViewController as a MyProtocol class.

+12  A: 

You can cast it like this:

if([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
    id<MyProtocol> p = (id<MyProtocol>)self.myViewController;
    [p protocolMethod];
}

This threw me for a bit, too. In Objective-C, the protocol isn't the type itself, so you need to specify id (or some other type, such as NSObject) along with the protocol that you want.

Andy
Ah, cool, thanks. I just checked and saw that casting it as `(id)` works too. Is that bad form?
Ford
If you cast it as id<MyProtocol> then the compiler will warn you if you use methods that aren't defined in that protocol.
dreamlax
@dreamlax - This is how the compiler does type checking against protocols. See http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_7_section_11.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF151 for more info.
Andy
@Ford - it would be better to use the the protocol specifically, since that way the compiler can perform some type checking for you.
Andy
@Andy, I don't think you need the '*' since 'id' is already a pointer. So: id<MyProtocol> p = (id<MyProtocol>)self.myViewController; [p protocolMethod];Or just: [(id<MyProtocol>)self.myViewController protocolMethod];
Ford