我想在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
答案 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)
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)
放入.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") \
对类似问题进行this question编辑......
答案 6 :(得分:2)
答案 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的技术都不适合我,原因不明。