Приведение экземпляра класса к протоколу @в Objective-C


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

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

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

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

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

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

2 91

2 ответа:

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

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

The UIViewController <MyProtocol> * type-cast переводится как "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) вместе с протоколом, который вы хотите.