Приведите экземпляр класса к @protocol в Objective-C
-
03-07-2019 - |
Вопрос
У меня есть объект (UIViewController), который может соответствовать или не соответствовать протоколу, который я определил.
Я знаю, что могу определить, соответствует ли объект протоколу, а затем безопасно вызвать метод:
if([self.myViewController conformsToProtocol:@protocol(MyProtocol)]) {
[self.myViewController protocolMethod]; // <-- warning here
}
Тем не менее, XCode показывает предупреждение:
warning 'UIViewController' may not respond to '-protocolMethod'
Как правильно предотвратить это предупреждение? Я не могу назвать self.myViewController
классом MyProtocol
.
Решение
Правильный способ сделать это - сделать:
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
следует использовать только в том случае, если вы не знаете класс / тип объекта, который приводится.
Другие советы
Вы можете разыграть его так:
if([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
id<MyProtocol> p = (id<MyProtocol>)self.myViewController;
[p protocolMethod];
}
Это меня тоже немного отбросило. В Objective-C протокол не является самим типом, поэтому вам нужно указать id
(или другой тип, например NSObject
) вместе с нужным протоколом.