Приведите экземпляр класса к @protocol в Objective-C - PullRequest
94 голосов
/ 06 марта 2009

У меня есть объект (UIViewController), который может соответствовать или не соответствовать протоколу, который я определил.

Я знаю, что могу определить, соответствует ли объект протоколу, а затем безопасно вызвать метод:

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

Однако XCode показывает предупреждение:

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

Как правильно предотвратить это предупреждение? Кажется, я не могу разыграть self.myViewController как MyProtocol класс.

Ответы [ 2 ]

160 голосов
/ 26 ноября 2010

Правильный способ сделать это - сделать:

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

Приведение типа UIViewController <MyProtocol> * преобразуется в «vc - это объект UIViewController, соответствующий MyProtocol», тогда как использование id <MyProtocol> переводит в «vc - это объект неизвестного класса, соответствующий MyProtocol».

Таким образом, компилятор даст вам правильную проверку типа на vc - компилятор выдаст вам предупреждение только в том случае, если вызван какой-либо метод, который не объявлен в UIViewController или <MyProtocol>. id следует использовать только в том случае, если вы не знаете класс / тип объекта, который будет кастоваться.

58 голосов
/ 06 марта 2009

Вы можете разыграть это так:

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

Это меня тоже немного отбросило. В Objective-C протокол не является самим типом, поэтому вам нужно указать id (или другой тип, например NSObject) вместе с нужным протоколом.

...