Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Xcode complain about undeclared methods when using @selector?

Why are warnings generated when calling methods undeclared in a class interface using conventional means, but not when calling methods using @selector? Is it because selectors can be executed by a different caller than self?

For example:

-(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
like image 741
btt Avatar asked Aug 13 '11 16:08

btt


4 Answers

The "Undeclared Selector" warning is turned off by default. I don't know why. You can turn it back on in the Build Settings.

The documentation for this settings reads:

Warn if a "@selector(...)" expression referring to an undeclared selector is found. A selector is considered undeclared if no method with that name has been declared before the "@selector(...)" expression, either explicitly in an @interface or @protocol declaration, or implicitly in an @implementation section. This option always performs its checks as soon as a "@selector(...)" expression is found, while -Wselector only performs its checks in the final stage of compilation. This also enforces the coding style convention that methods and selectors must be declared before being used. [GCC_WARN_UNDECLARED_SELECTOR, -Wundeclared-selector]

like image 88
rbrown Avatar answered Oct 05 '22 23:10

rbrown


A similar question was asked on SO a few weeks ago.

This is basically because selectors are late-bound. They're not looked up until runtime. There are options for forcing verification during compilation. The question I linked to has some more information on how you can do that.

like image 27
csano Avatar answered Oct 06 '22 00:10

csano


The way @selector works by default is you are telling the compiler; trust me I have this method somewhere in my class. Its the same concept if you do @class yourclassname instead of importing the .h file which contains the class.

like image 23
user893339 Avatar answered Oct 05 '22 22:10

user893339


This is because the compiler needs to know the signature of the method in order to call it (i.e. [self doNow];), because such a call translates to either a call to objc_msgSend or objc_msgSend_stret depending on whether the method signature has a return type of a struct or not. (Remember the difference between the selector (simply the name with the colons in it, but with no types) and the signature (the types) of a method.) So it needs to warn because it could be calling the wrong function if it doesn't know.

However, just getting a selector (@selector(...)), it doesn't need to know the types. The selector is simply a name, and you've provided the name. It's all about what you use the selector for. If you use it in performSelector:, it also doesn't need to know the types, because that method only works for methods with argument and return types of objects, so there is no ambiguity. Hence there is no need for a warning.

like image 45
newacct Avatar answered Oct 05 '22 23:10

newacct