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


Я хочу использовать селектор на экземпляре NSObject без необходимость реализации протокола. Например, существует метод category, который должен установить свойство error, если экземпляр 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: метод или свойство.

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

спасибо,
ЕР

11 153

11 ответов:

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

#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

посмотреть NSSelectorFromString.

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

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

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

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

SEL setErrorSelector = sel_registerName("setError:");

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

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

в разделе 'Apple LLVM warnings-Objective-C', изменить:

Undeclared Selector - NO

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

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

@interface Yourclass (PrivateMethods)

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

@end

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

очень удобный макрос, чтобы положить в свой .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")                                         \

- это правка этот вопрос для подобной проблеме...

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

enter image description here

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

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

хотя правильный ответ, вероятно, заключается в информировании Xcode через импорт или регистрацию селектора о том, что такой селектор существует, в моем случае мне не хватало точки с запятой. Убедитесь, что перед тем, как" исправить " ошибку, возможно, ошибка правильная, а ваш код нет. я нашел ошибку в образце Mvcnetworking от Apple, например.

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

    [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
{

}

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