Как избавиться от предупреждения "необъявленного селектора"
Я хочу использовать селектор экземпляра 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
{
}
В то время как я ценю знание того, как скрыть предупреждение, лучше это исправлять, и ни технологии Серджио, ни Релкин не работали для меня по неизвестным причинам.