@ Энди, я не думаю, что тебе нужен '*', так как 'id' уже является указателем. Итак: id <MyProtocol> p = (id <MyProtocol>) self.myViewController; [p protocolMethod]; Или просто: [(id <MyProtocol>) self.myViewController protocolMethod];

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

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

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

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

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

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

Ответы на вопрос(1)

Решение Вопроса

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 следует использовать только в ситуации, если вы не знаете класс / тип объекта, который был приведен.

 memmons30 нояб. 2013 г., 18:13
При использовании протоколов вы действительно не должны заботиться о типе объекта - суть протокола в том, что любой тип объекта может принять его и использовать без приведения к конкретному объекту. Поэтому я бы рекомендовал использовать ответ @andy в любом месте, где вы применяете протокол, а не выше -id<MyProtocol> p = (id<MyProtocol>)self.myViewController; Этот ответ и @andys оба верны, но егоБольше верный.
 memmons01 дек. 2013 г., 17:14
Не уверен, что в отношении моего комментария неверно? В любом случае, если вы проверяете, соответствует ли объект протоколу, зачем вам тогда вызывать какой-то другой метод, не связанный с протоколом? Я не могу вспомнить когда-либо необходимость делать это или видеть это в коде, который я рассмотрел. Похоже, запах кода для меня.
 Nick Forge01 дек. 2013 г., 16:41
@ Отвечает на ваш комментарий неверно, и пропускает замечание, которое я сделал в последнем абзаце моего ответа. Вы можете или не можете заботиться о типе объекта, это зависит от ситуации. Что произойдет, если вы хотите отправить сообщение, объявленное наUIViewController вvc в примере в моем ответе, и он объявлен какid <MyProtocol>?
 Nick Forge02 дек. 2013 г., 02:43
То, что вы его не видели / не использовали, не означает, что это запах кода. Вот фрагмент кода, показывающий один пример того, как выбрасывать информацию о типе с помощьюid это проблема:gist.github.com/nsforge/7743616

Ваш ответ на вопрос