为什么在使用常规方法调用类接口中未声明的方法时会生成警告,但在使用@selector调用方法时却不会?是因为选择器可以由不同的调用者执行吗?
例如:
-(void) doStuff
{
[self doNow]; // Warning: instance method not found
SEL sel = @selector(doNow); // no warnings
}
-(void) doNow {} // this method is not declared in the interface
答案 0 :(得分:14)
默认情况下,“未声明的选择器”警告处于关闭状态。我不知道为什么。您可以在Build Settings中重新打开它。
此设置的文档为:
如果找到引用未声明选择器的“@selector(...)”表达式,则发出警告。如果在“@selector(...)”表达式之前没有声明具有该名称的方法,则选择器被视为未声明,在@interface或@protocol声明中显式声明,或隐式在@implementation部分中声明。一旦找到“@selector(...)”表达式,此选项始终执行其检查,而-Wselector仅在编译的最后阶段执行其检查。这也强制执行编码样式约定,即在使用之前必须声明方法和选择器。 [GCC_WARN_UNDECLARED_SELECTOR,-Wundeclared-selector]
答案 1 :(得分:4)
几周前在SO上问过类似的question。
这基本上是因为选择器是后期绑定的。它们直到运行时才被查找。在编译期间有强制验证的选项。我链接的问题有关于如何做到这一点的更多信息。
答案 2 :(得分:2)
默认情况下@selector的工作方式是告诉编译器;相信我,我在班上的某个地方有这种方法。如果您使用@class yourclassname而不是导入包含该类的.h文件,则它的概念相同。
答案 3 :(得分:2)
这是因为编译器需要知道方法的签名才能调用它(即[self doNow];
),因为这样的调用转换为对objc_msgSend
或{{1}的调用取决于方法签名是否具有objc_msgSend_stret
的返回类型。 (记住选择器之间的区别(只是带有冒号的名称,但没有类型)和方法的签名(类型)。所以它需要警告,因为它可能会调用错误的函数,如果它没有不知道。
但是,只需获取选择器(struct
),就不需要知道类型。选择器只是一个名称,您已经提供了名称。这都是关于你使用选择器的原因。如果在@selector(...)
中使用它,它也不需要知道类型,因为该方法仅适用于具有参数和返回类型的对象的方法,因此没有歧义。因此,不需要警告。