如何摆脱'未声明的选择器'警告

时间:2011-06-03 08:57:27

标签: objective-c selector categories

我想在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

11 个答案:

答案 0 :(得分:246)

另一种选择是通过以下方式禁用警告:

#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

答案 1 :(得分:186)

查看NSSelectorFromString

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

它允许您在运行时创建选择器,而不是在编译时通过@selector关键字创建选择器,编译器将没有机会抱怨。

答案 2 :(得分:51)

我认为这是因为出于某种奇怪的原因,选择器未在运行时注册。

尝试通过sel_registerName()注册选择器:

SEL setErrorSelector = sel_registerName("setError:");

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

答案 3 :(得分:7)

我通过#include使用该方法的文件来消除该消息。该文件中没有使用任何其他内容。

答案 4 :(得分:5)

如果你的类实现了setError:方法(甚至通过声明动态最终错误属性的setter)你可能想在接口文件(.h)中声明它,或者如果你不想显示它你可以尝试使用PrivateMethods棘手的技巧:

@interface Yourclass (PrivateMethods)

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

@end

在@implementation之前,这应该隐藏警告;)。

答案 5 :(得分:3)

放入.pchCommon.h或您想要的任何地方的非常舒适的宏:

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

对类似问题进行this question编辑......

答案 6 :(得分:2)

您可以在Xcode中将其关闭,如屏幕截图所示:

enter image description here

答案 7 :(得分:1)

您还可以首先将有问题的对象转换为id,以避免出现警告:

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

答案 8 :(得分:1)

避免此警告的另一种方法是确保选择器方法如下所示:

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

如果您想接受任何发件人,或者愿意,请指定一个发件人对象的类型,不要忘记“(id)发件人”。

答案 9 :(得分:0)

虽然正确的答案可能在于通过导入通知Xcode或注册这样的选择器存在的选择器,但在我的情况下,我错过了一个分号。确保在“修复”错误之前,可能是错误,错误是正确的,而代码则没有。例如,我在Apple的MVCNetworking示例中发现了错误。

答案 10 :(得分:-1)

我能够通过添加一些方法得到警告消失(披露:我没有想到这一点,但是通过在timetimerwithtimeinterval上搜索来找到它)

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

}

虽然我很高兴知道如何隐藏警告,但是修理它会更好,而且Sergio和Relkin的技术都不适合我,原因不明。