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

epo*_*gee 160 objective-c selector categories

我想在NSObject实例上使用选择器,而不需要实现协议.例如,如果调用它的NSObject实例支持它,则应该设置一个类别方法.这是代码,代码按预期工作:

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

但是,编译器看不到setError:signature的任何方法,因此它为包含该@selector(setError:)代码段的每一行提供了警告:

Undeclared selector 'setError:'
Run Code Online (Sandbox Code Playgroud)

我不想声明一个协议来摆脱这个警告,因为我不希望所有可能使用它的类实现任何特殊的东西.按惯例,我希望他们有setError:方法或财产.

这可行吗?怎么样?

干杯,
EP

Kla*_*aas 248

另一个选择是禁用警告:

#pragma GCC diagnostic ignored "-Wundeclared-selector"
Run Code Online (Sandbox Code Playgroud)

您可以将此行放在发生警告的.m文件中.

更新:

它也适用于LLVM,如下所示:

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

... your code here ...

#pragma clang diagnostic pop
Run Code Online (Sandbox Code Playgroud)


ser*_*gio 193

看看NSSelectorFromString.

 SEL selector = NSSelectorFromString(@"setError:");
 if ([self respondsToSelector:selector])
Run Code Online (Sandbox Code Playgroud)

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

  • 不确定它是否是Xcode 5,但我对此实现有不同的警告:_"PerformSelector可能导致泄漏,因为它的选择器未知"_. (15认同)
  • 我更喜欢这个答案,因为它看起来更像"Cocoa"-y(?).`sel_registerName()`thingy看起来很模糊,你不应该直接调用它,除非你知道你在做什么,有点像obj_msg_send();) (2认同)

Jac*_*kin 52

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

尝试通过sel_registerName()以下方式注册选择器:

SEL setErrorSelector = sel_registerName("setError:");

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

  • 不确定它是否是Xcode 5,但我对此实现有不同的警告:_"PerformSelector可能导致泄漏,因为它的选择器未知"_. (8认同)
  • 无论如何,@ epologee`NSSelectorFromString`在引擎盖下调用`sel_registerName()`.选择最适合你的人. (2认同)
  • @epologee 我认为直接调用 `sel_registerName()` 更明确地说明你为什么这样做。`NSSelectorFromString` 不会*告诉*您它将尝试注册选择器。 (2认同)

Mar*_*son 7

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

  • 最高投票的答案都不正确."未声明的选择器"警告的目的是在编译时捕获错误,如果您更改您依赖的选择器的名称.因此,#import声明您所依赖的方法的文件是最正确的. (2认同)

Ian*_*anS 7

我意识到这个线程有点迟了但是为了完整性,你可以使用目标构建设置全局关闭此警告.

在"Apple LLVM警告 - Objective-C"部分中,更改:

Undeclared Selector - NO
Run Code Online (Sandbox Code Playgroud)


i_m*_*ush 5

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

@interface Yourclass (PrivateMethods)

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

@end
Run Code Online (Sandbox Code Playgroud)

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