Почему Xcode не жалуется на необъявленные методы при использовании @selector? - PullRequest
5 голосов
/ 13 августа 2011

Почему предупреждения генерируются при необъявленном вызове методов в интерфейсе класса с использованием обычных средств, а не при вызове методов с использованием @selector?Это потому, что селекторы могут быть выполнены другим абонентом, чем я?

Например:

-(void) doStuff
{
    [self doNow]; // Warning: instance method not found
    SEL sel = @selector(doNow); // no warnings
}   

-(void) doNow {} // this method is not declared in the interface

Ответы [ 4 ]

14 голосов
/ 13 августа 2011

Предупреждение «Необъявленный селектор» по умолчанию отключено.Я не знаю почему.Вы можете включить его снова в настройках сборки.

Документация по этим настройкам гласит:

Предупредить, если найдено выражение "@selector (...)", ссылающееся на необъявленный селектор.Селектор считается необъявленным, если ни один метод с таким именем не был объявлен перед выражением "@selector (...)", явно в объявлении @interface или @protocol или неявно в разделе @implementation.Эта опция всегда выполняет свои проверки, как только найдено выражение "@selector (...)", в то время как -Wselector выполняет свои проверки только на финальной стадии компиляции.Это также обеспечивает соблюдение стиля кодирования, согласно которому методы и селекторы должны быть объявлены перед использованием.[GCC_WARN_UNDECLARED_SELECTOR, -Wundeclared-selector]

4 голосов
/ 13 августа 2011

Подобный вопрос был задан на SO несколько недель назад.

Это в основном потому, что селекторы имеют позднюю привязку. Они не смотрели до времени выполнения. Есть варианты для принудительной проверки во время компиляции. Вопрос, на который я ссылался, содержит дополнительную информацию о том, как вы можете это сделать.

2 голосов
/ 24 января 2012

Это потому, что компилятору необходимо знать сигнатуру метода для его вызова (т. Е. [self doNow];), потому что такой вызов преобразуется либо в вызов objc_msgSend, либо objc_msgSend_stret в зависимости от того, является ли методподпись имеет тип возврата struct или нет.(Запомните разницу между селектором (просто именем с двоеточиями в нем, но без типов) и сигнатурой (типами) метода.) Поэтому необходимо предупредить, потому что он может вызывать неправильную функцию, если неНе знаю.

Однако, просто получив селектор (@selector(...)), ему не нужно знать типы.Селектор - это просто имя, и вы указали имя.Это все о том, для чего вы используете селектор.Если вы используете его в performSelector:, ему также не нужно знать типы, потому что этот метод работает только для методов с аргументами и возвращает типы объектов, поэтому нет никакой двусмысленности.Следовательно, нет необходимости в предупреждении.

2 голосов
/ 13 августа 2011

По умолчанию @selector работает так, как вы говорите компилятору; поверьте мне, у меня есть этот метод где-то в моем классе. Это та же концепция, если вы делаете @class yourclassname вместо импорта файла .h, который содержит класс.

...