How to get rid of the 'undeclared selector' warning
Objective CSelectorCategoriesObjective C Problem Overview
I want to use a selector on an NSObject instance without the need for an implemented protocol. For example, there's a category method that should set an error property if the NSObject instance it's called on supports it. This is the code, and the code works as intended:
if ([self respondsToSelector:@selector(setError:)])
{
[self performSelector:@selector(setError:) withObject:[NSError errorWithDomain:@"SomeDomain" code:1 userInfo:nil]];
}
However, the compiler doesn't see any method around with the setError: signature, so it gives me a warning, for each line that contains the @selector(setError:)
snippet:
Undeclared selector 'setError:'
I don't want to have to declare a protocol to get rid of this warning, because I don't want all classes that may use this to implement anything special. Just by convention I want them to have a setError:
method or property.
Is this doable? How?
Cheers,
EP
Objective C Solutions
Solution 1 - Objective C
Another option would be to disable the warning with:
#pragma GCC diagnostic ignored "-Wundeclared-selector"
You can place this line in the .m file where the warning occurs.
Update:
It works also with LLVM like this:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
... your code here ...
#pragma clang diagnostic pop
Solution 2 - Objective C
Have a look at NSSelectorFromString.
SEL selector = NSSelectorFromString(@"setError:");
if ([self respondsToSelector:selector])
It will allow you to create a selector at runtime, instead of at compile time through the @selector
keyword, and the compiler will have no chance to complain.
Solution 3 - Objective C
I think this is because for some odd reason the selector isn't registered with the runtime.
Try registering the selector via sel_registerName()
:
SEL setErrorSelector = sel_registerName("setError:");
if([self respondsToSelector:setErrorSelector]) {
[self performSelector:setErrorSelector withObject:[NSError errorWithDomain:@"SomeDomain" code:1 userInfo:nil]];
}
Solution 4 - Objective C
If your class implements the setError: method (even by declaring dynamic the setter of the eventual error property) you might want to declare it in your interface file ( .h), or if you don't like to show it that way you could try with the PrivateMethods tricky trick:
@interface Yourclass (PrivateMethods)
- (void) yourMethod1;
- (void) yourMethod2;
@end
just before your @implementation , this should hide the warnings ;).
Solution 5 - Objective C
I got that message to go away by #include'ing the file with the method. Nothing else was used from that file.
Solution 6 - Objective C
I realise I'm a bit late to this thread but for completeness, you can globally turn off this warning using the target build settings.
In section, 'Apple LLVM warnings - Objective-C', change:
Undeclared Selector - NO
Solution 7 - Objective C
Another way to avoid this warning is to make sure your selector method looks like this:
-(void) myMethod :(id) sender{
}
Don't forget "(id) sender" if you want to accept any sender or specify a type of a sender object if you prefer.
Solution 8 - Objective C
A really comfortable macro to put in your .pch
or Common.h
or wherever you want:
#define SUPPRESS_UNDECLARED_SELECTOR_LEAK_WARNING(code) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wundeclared-selector"\"") \
code; \
_Pragma("clang diagnostic pop") \
It's an edit of this question for similar issue...
Solution 9 - Objective C
Solution 10 - Objective C
You can also cast the object in question to an id first to avoid the warning:
if ([object respondsToSelector:@selector(myMethod)]) {
[(id)object myMethod];
}
Solution 11 - Objective C
While the correct answer likely lies in informing Xcode through imports or registering the selector that such a selector exists, in my case I was missing a semi-colon. Make sure before you "fix" the error that perhaps, the error is correct and your code isn't. I found the error in Apple's MVCNetworking sample, for instance.
Solution 12 - Objective C
I was able to get the warning to go away by adding thenothing method (disclosure: I didn't think of this but found it by googling on scheduledtimerwithtimeinterval)
[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
{
}
While I appreciate knowing how to hide the warning, fixing it is better and neither Sergio's nor Relkin's techniques worked for me, for unknown reasons.