Monday, April 25, 2011

Cast an instance of a class to a @protocol in Objective-C

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.

From stackoverflow
  • 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.

    Ford : Ah, cool, thanks. I just checked and saw that casting it as `(id)` works too. Is that bad form?
    dreamlax : If you cast it as id then the compiler will warn you if you use methods that aren't defined in that protocol.
    Andy : @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.
    Ford : @Andy, I don't think you need the '*' since 'id' is already a pointer. So: id p = (id)self.myViewController; [p protocolMethod]; Or just: [(id)self.myViewController protocolMethod];

0 comments:

Post a Comment