Как избавиться от предупреждения «необъявленный селектор» - PullRequest
160 голосов
/ 03 июня 2011

Я хочу использовать селектор в экземпляре NSObject без необходимости в реализованном протоколе. Например, есть метод категории, который должен установить свойство ошибки, если экземпляр NSObject, к которому он вызывается, поддерживает его. Это код, и код работает как задумано:

if ([self respondsToSelector:@selector(setError:)])
{
    [self performSelector:@selector(setError:) withObject:[NSError errorWithDomain:@"SomeDomain" code:1 userInfo:nil]];
}

Однако компилятор не видит никакого метода с setError: signature, поэтому он выдает предупреждение для каждой строки, содержащей фрагмент @selector(setError:):

Undeclared selector 'setError:'

Я не хочу объявлять протокол, чтобы избавиться от этого предупреждения, потому что я не хочу, чтобы все классы могли использовать это для реализации чего-то особенного. Я просто хочу, чтобы у них был метод или свойство setError:.

Это выполнимо? Как?

Приветствия
EP

Ответы [ 12 ]

247 голосов
/ 09 мая 2012

Другой вариант - отключить предупреждение с помощью:

#pragma GCC diagnostic ignored "-Wundeclared-selector"

Вы можете поместить эту строку в файл .m, где появляется предупреждение.

Обновление:

Это также работает с LLVM:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"

... your code here ...

#pragma clang diagnostic pop
189 голосов
/ 03 июня 2011

Посмотрите на NSSelectorFromString .

 SEL selector = NSSelectorFromString(@"setError:");
 if ([self respondsToSelector:selector])

Это позволит вам создать селектор во время выполнения, а не во время компиляции с помощью ключевого слова @selector и компиляторане будет возможности пожаловаться.

51 голосов
/ 03 июня 2011

Я думаю, это потому, что по какой-то странной причине селектор не зарегистрирован во время выполнения.

Попробуйте зарегистрировать селектор через sel_registerName():

SEL setErrorSelector = sel_registerName("setError:");

if([self respondsToSelector:setErrorSelector]) {
   [self performSelector:setErrorSelector withObject:[NSError errorWithDomain:@"SomeDomain" code:1 userInfo:nil]];
}
7 голосов
/ 30 апреля 2015

Я понимаю, что немного опоздал к этой теме, но для полноты вы можете глобально отключить это предупреждение, используя настройки сборки цели.

В разделе «Предупреждения Apple LLVM - Objective-C»,изменить:

Undeclared Selector - NO
7 голосов
/ 05 ноября 2013

Я получил это сообщение, чтобы уйти # включив файл с методом.Из этого файла больше ничего не использовалось.

5 голосов
/ 03 июня 2011

Если ваш класс реализует метод setError: (даже объявив динамически установщик свойства возможной ошибки), вы можете объявить его в своем файле интерфейса (.h) или не хотите показывать, что как вы можете попробовать хитрый трюк с PrivateMethods:

@interface Yourclass (PrivateMethods)

- (void) yourMethod1;
- (void) yourMethod2;

@end

как раз перед вашей @implementation, это должно скрыть предупреждения;).

3 голосов
/ 13 апреля 2014

Действительно удобный макрос, который можно вставить в .pch или Common.h или куда угодно:

#define SUPPRESS_UNDECLARED_SELECTOR_LEAK_WARNING(code)                        \
_Pragma("clang diagnostic push")                                        \
_Pragma("clang diagnostic ignored \"-Wundeclared-selector"\"")     \
code;                                                                   \
_Pragma("clang diagnostic pop")                                         \

Это редактирование этого вопроса для аналогичного вопроса ...

2 голосов
/ 14 ноября 2018

Другой способ избежать этого предупреждения - убедиться, что ваш метод селектора выглядит следующим образом:

-(void) myMethod :(id) sender{
}

Не забудьте "(id) отправителя", если вы хотите принять любого отправителя или указать типобъекта отправителя, если вы предпочитаете.

2 голосов
/ 11 октября 2016

Вы можете отключить его в Xcode, как на скриншоте:

enter image description here

1 голос
/ 05 августа 2014

Вы также можете сначала привести рассматриваемый объект к идентификатору, чтобы избежать предупреждения:

if ([object respondsToSelector:@selector(myMethod)]) {
    [(id)object myMethod];
}
...