Converter uma instância de uma classe para um @protocol em Objective-C
-
03-07-2019 - |
Pergunta
Eu tenho um objeto (a UIViewController), que pode ou não estar de acordo com um protocolo que eu definido.
Eu sei que posso determinar se o objeto está em conformidade com o protocolo, em seguida, chamar com segurança o método:
if([self.myViewController conformsToProtocol:@protocol(MyProtocol)]) {
[self.myViewController protocolMethod]; // <-- warning here
}
No entanto, XCode exibe um aviso:
warning 'UIViewController' may not respond to '-protocolMethod'
O que é o caminho certo para evitar este aviso? Eu não consigo self.myViewController
elenco como uma classe MyProtocol
.
Solução
A maneira correta de fazer isso é fazer:
if ([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
UIViewController <MyProtocol> *vc = (UIViewController <MyProtocol> *) self.myViewController;
[vc protocolMethod];
}
O UIViewController <MyProtocol> *
tipo elenco se traduz em "vc é um objeto UIViewController em conformidade com MyProtocol", enquanto usando id <MyProtocol>
se traduz em "vc é um objeto de uma classe desconhecida em conformidade com MyProtocol".
Desta forma, o compilador irá dar-lhe a verificação de tipo adequada sobre vc
- o compilador só vai te dar um aviso se qualquer método que não é declarado em ambos UIViewController
ou <MyProtocol>
é chamado. id
só deve ser usado na situação, se você não sabe a classe / tipo do objeto sendo elenco.
Outras dicas
Você pode lançá-lo como este:
if([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
id<MyProtocol> p = (id<MyProtocol>)self.myViewController;
[p protocolMethod];
}
Esta me jogou para um pouco, também. Em Objective-C, o protocolo não é o próprio tipo, então você precisa especificar id
(ou algum outro tipo, como NSObject
), juntamente com o protocolo que você deseja.