当我尝试将@selector(xxx)与在同一源文件中实际未定义的任何方法一起使用时,Xcode 4给出了(相当无益的)关于“未实现的选择器'xxx'”的错误。如果我将LLVM编译器警告“选择器的多个定义类型”设置为“否”,则错误消失(至少对于项目构建)。 (这是iOS默认设置,但对于我的项目,它已启用。)但是,即使关闭此选项,如果在“构建设置”对话框中选中“启用实时问题”,错误仍会显示在编辑器中。< /击>
所以现在我已经关闭了实时问题,以免分心,这有点让人失望。我的问题是:有没有办法可以通过指定我想要使用的选择器的哪个定义来摆脱错误?或者它应该是否重要,即方法的所有定义是否在Objective-C中共享相同的选择器?这是一个编译器错误,还是一个虚假的设置,我应该放弃? (如果是后者,为什么新编辑器中的实时构建功能会出现?)
这是代码,只是为了清楚:
if ([recognizer respondsToSelector:@selector(translationInView:)]) {
...
}
这是错误:
error: unimplemented selector 'translationInView:' [-Wselector,2]
if ([recognizer respondsToSelector:@selector(translationInView:)]) {
^
如果我用同一源文件中定义的方法替换'translationInView:',则没有错误。我已经导入了定义此方法的标头,我尝试在此源文件中的类别中声明该方法。没关系。
我现在正在关闭警告并继续生活并继续前进,但我很想找到更好的解决方案来解决这个问题。至少,我想了解Objective-C的@selector是否具有选择方法的特定定义的语法,因为到目前为止我还没有找到任何符号。
谢谢!
答案 0 :(得分:5)
选择器与定义没有任何联系。在它的基本级别,它实际上只是一个标识方法的名称的唯一值。以下方法都具有完全相同的选择器:
- (void)doSomething:(id)foo;
- (int)doSomething:(NSUInteger)i;
- (void (*)())doSomething:(char *)name;
这些方法都具有完全相同的选择器@selector(doSomething:)
。
我相信问题是当你引用@selector(translationInView:)
编译器告诉你它从未见过任何方法,在任何地方,都有那个选择器,虽然我不能确定因为你没有粘贴你的确切错误。您应该确保声明此方法的头文件实际上已导入到当前文件中。或者,如果你不能这样做,你总是可以在NSObject上的类别中声明方法,如下所示:
@interface NSObject (SelectorStuff)
- (CGPoint)translationInView:(UIView *)view;
@end
这将告诉编译器这个选择器是否存在,虽然它也会产生副作用,允许你在这个文件中的任何对象上调用[foo translationInView:bar]
而不会收到警告(当然,这仍然会失败)运行时)。
答案 1 :(得分:1)
From the Objective-C Programming Language Guide:
编译的选择器属于SEL类型。 所有具有相同名称的方法都有 相同的选择器。
...
为了提高效率,请使用完整的ASCII名称 不用作方法选择器 编译代码。相反,编译器 将每个方法名称写入表中, 然后将名称与唯一对称 表示方法的标识符 在运行时。运行时系统 确保每个标识符都是唯一的:没有两个 选择器是相同的,都是 具有相同名称的方法具有 相同的选择器。
就选择器而言,定义并不重要......只有方法的名称。
答案 2 :(得分:0)
如果您正在使用GCC前端,则必须设置此标志以获取这些警告:
-Wundeclared-selector
请注意,默认情况下不会设置此标志,因此必须以某种方式将其添加到构建配置中,以便您立即看到警告。
答案 3 :(得分:0)
我个人认为这是编译器中的一个错误,因为即使选择器在另一个类别中声明,错误也会出现,在这种情况下编译器应该安全地假设它没有在 this < / em>源文件。编译器应将此标记为可在链接时确认的问题,并且只有在链接所有对象/库时确实没有实现才会导致此警告。