如何消除“未声明的选择器”警告

我想在 NSObject 实例 没有上使用一个选择器,以满足实现协议的需要。例如,如果所调用的 NSObject 实例支持类别方法,则该方法应该设置错误属性。这是代码,代码按预期运行:

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

但是,编译器没有看到任何带有 setError: sign 的方法,因此对于包含 @selector(setError:)代码片段的每一行,它都会给我一个警告:

Undeclared selector 'setError:'

我不希望必须声明一个协议来消除这个警告,因为我不希望所有可能使用这个协议的类实现任何特殊的东西。按照惯例,我希望它们具有 setError:方法或属性。

这可行吗,怎么可行?

干杯,
执行制片人

79901 次浏览

看看 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]];
}

如果您的类实现了 setError: method (甚至通过动态声明最终 error 属性的 setter) ,那么您可能希望在接口文件(。H) ,或者如果你不喜欢用这种方式展示它,你可以尝试一下 PrivateMethod 的技巧:

@interface Yourclass (PrivateMethods)


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


@end

在@实现之前,这应该会隐藏警告;)。

另一种选择是使用以下命令禁用警告:

#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

虽然正确的答案可能在于通过导入或注册选择器来通知 Xcode 存在这样一个选择器,但在我的例子中,我遗漏了一个分号。在“修复”错误之前,请确保该错误是正确的,而您的代码是错误的。例如,我在苹果的 MVCNetworking 示例中发现了错误。

我通过 # include‘ ing the file with the method 得到了消息。文件里没有其他信息。

一个真正舒适的宏放在你的 .pchCommon.h或任何你想要的地方:

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

这是一个编辑的 这个问题类似的问题..。

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

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

通过添加 Nothing 方法(披露: 我没有想到这一点,但通过在调度计时器和时间间隔上谷歌搜索找到了它) ,我得到了消失的警告

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


}

虽然我很感激知道如何隐藏警告,修复它是更好的,无论是塞尔吉奥的还是雷尔金的技术为我工作,出于未知的原因。

我意识到我有点晚了这个线程,但为了完整性,您可以在全局关闭这个警告使用目标构建设置。

在“ Apple LLVM 警告-Objective-C”部分,更改:

Undeclared Selector - NO

你可以在 Xcode 像截图那样关掉它:

enter image description here

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

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

如果希望接受任何发送方,请不要忘记“(id) sender”,如果愿意,请指定发送方对象的类型。