Как избавиться от предупреждения "необъявленного селектора"

Я хочу использовать селектор экземпляра 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:.

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

Cheers,
ЕР

Ответ 1

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

#pragma GCC diagnostic ignored "-Wundeclared-selector"

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

Update:

Он также работает с LLVM следующим образом:

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

... your code here ...

#pragma clang diagnostic pop

Ответ 2

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

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

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

Ответ 3

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

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

SEL setErrorSelector = sel_registerName("setError:");

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

Ответ 4

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

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

Undeclared Selector - NO

Ответ 5

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

Ответ 6

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

@interface Yourclass (PrivateMethods)

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

@end

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

Ответ 7

Действительно удобный макрос для размещения в .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")                                         \

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

Ответ 8

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

введите описание изображения здесь

Ответ 9

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

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

Ответ 10

Хотя правильный ответ, вероятно, заключается в информировании Xcode посредством импорта или регистрации селектора, который существует в этом селекторе, в моем случае у меня отсутствовала точка с запятой. Перед тем, как исправить ошибку, убедитесь, что ошибка правильная, а ваш код - нет. Например, я нашел ошибку в примере Apple MVCNetworking.

Ответ 11

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

    [NSTimer scheduledTimerWithTimeInterval:[[NSDate distantFuture] timeIntervalSinceNow]
                                     target:self
                                   selector:@selector(donothingatall:)
                                   userInfo:nil
                                    repeats:YES];


    [[NSRunLoop currentRunLoop] run];

    HTTPLogVerbose(@"%@: BonjourThread: Aborted", THIS_FILE);

    }
}

+ (void) donothingatall:(NSTimer *)timer
{

}

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