Re: Creating selector for nonexistent method
Re: Creating selector for nonexistent method
- Subject: Re: Creating selector for nonexistent method
- From: Charles Srstka <email@hidden>
- Date: Tue, 29 Apr 2014 13:38:06 -0500
On Apr 29, 2014, at 8:18 AM, Arved von Brasch <email@hidden> wrote:
> Hi List,
>
> I have a warning that I’m trying to understand. Hopefully someone here can shed some light on it.
>
> I have two relevant classes. My window controller:
>
> @interface ISWindowController : NSWindowController <NSToolbarDelegate>
> …
> - (IBAction)clear: (id)sender;
> ...
> @end
>
> This method is implemented and works as expected if called directly. (It clears the search field in the toolbar.)
>
> In the second class, an NSArrayController subclass, I have the following method override:
>
> - (id)newObject {
> NSManagedObject *newObject = [super newObject];
> ...
> // Clear the Search Field via the Window Controller (Responder Chain)
> [NSApp sendAction: @selector(clear:) to: nil from: table];
> …
> }
>
> sendAction:to:from: seems to be the preferred way to invoke the responder chain to implement the clear: method in the Window controller. However, it generates the following warning:
>
> “Creating selector for nonexistent method ‘clear:’
>
> I can’t figure out how to get rid of this warning. The window controller’s header file is imported into the second class. Removing the import causes a second warning to be generated on the same line, which is what I expected (Undeclared selector). I’ve also tried using other ways of invoking the responder chain, like tryToPerform:with: on the table the Array Controller is managing. It seems to be any attempt to use @selector() that is causing the warning.
>
> I know how to turn off this warning, what I’d like to understand is why it’s coming out at all. I thought I was doing everything right here.
I've been having the same issue, so I filed a Radar report on it a while back (rdar://16600230). The first case that was causing it was:
NSArray *array = ...;
NSArray *sortedArray = [array sortedArrayUsingSelector:@selector(compare:)]; // warns about nonexistent selector "compare:"
This one can be worked around by using -sortedArrayUsingComparator: instead. What can't be as easily worked around are things like this:
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem { // or -respondsToSelector:, +resolveInstanceMethod:, etc.
SEL action = menuItem.action;
// insert any framework-defined method here; we'll use -performTextFinderAction: as an example
if (sel_isEqual(action, @selector(performTextFinderAction:))) { // warns about nonexistent selector "performTextFinderAction:"
// do something
}
return [super validateMenuItem:menuItem];
}
As far as I can tell, the only way to make that work without warning is to use NSSelectorFromString, which of course undermines the purpose of having -Wselector turned on in the first place, since any typo in the selector string will remain unnoticed until it causes things to fail at runtime.
Unfortunately, my Radar report was closed with the status "Behaves Correctly." This was the rationale:
"Engineering has determined that this issue behaves as intended based on the following:
This warning is as expected. Intention of this warning is to warn about unimplemented methods in current TU when method is used in a @selector expression. Note that in user test case " -compare:" has been declared but not implemented.
But, why do we get this warning only if a random @implementation is added to the TU (as user discovered)?
This warning is issued only when the selector meta-data table is generated which requires at least one implementation. This warning comes from gcc's legacy and seems to enforce coding style that the @implementation in the TU must implement the method used in the @selector expression.
We are now closing this bug report.
If you have questions regarding the resolution of this issue, please update your bug report with that information.
Please be sure to regularly check new Apple releases for any updates that might affect this issue."
So it seems that even if the method is defined in a header, you need it to be in the @implementation block of a class for which you have the code in order to use @selector without setting off -Wselector. This means that @selector cannot be used for methods in framework classes. You will need to either use NSSelectorFromString, find a way to use a blocks-based approach (if it's possible), or just turn off -Wselector.
Charles
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden