Should I fix Xcode 5 'Semantic issue: undeclared selector'?
Asked Answered
H

4

30

I'm trying to upgrade my app with Xcode5 but encountered a number of 'Semantic issues' in a third party library (being MagicalRecord). The quickest way to 'fix' this might be using the:

#pragma GCC diagnostic ignored "-Wundeclared-selector"

(from: How to get rid of the 'undeclared selector' warning)

compiler directive, but my gut-feeling says this is not the appropriate way to do this. A small code sample with the above error:

+ (NSEntityDescription *) MR_entityDescriptionInContext:(NSManagedObjectContext *)context {

    if ([self respondsToSelector:@selector(entityInManagedObjectContext:)]) 
    {
        NSEntityDescription *entity = [self performSelector:@selector(entityInManagedObjectContext:) withObject:context];
        return entity;
    }
    else
    {
        NSString *entityName = [self MR_entityName];
        return [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
    }
}

where the entityInManagedObjectContext: method is not defined anywhere.

Any suggestions on how to best fix these types of errors, thanks in advance?!

Hermaherman answered 2/9, 2013 at 10:24 Comment(0)
M
21

You just need to declare a class or protocol that contains the selector. For example:

//  DeliveryTimeComparison.h
#import <Foundation/Foundation.h>

@protocol DeliveryTimeComparison <NSObject>

- (void)compareByDeliveryTime:(id)otherTime;

@end

And then simply #import "DeliveryTimeComparison.h" in any class where you plan to use @selector(compareByDeliveryTime:).

Or alternatively, just import the class header for any object that contains a "compareByDeliveryTime:" method.

Momus answered 2/10, 2013 at 22:47 Comment(2)
I agree with the above method, because turning off warnings is not my preferred way of 'fixing'. With the appropriate header file and class/protocol names I'm able to find this documented 'quick-fix' easier. So for the time being I think I'll adopt Abhi's method.Hermaherman
This sounds fine unless you can't really include/import the class where the selector should be (cycle dependency problems, ..)Underwaist
D
25

Yes you should.

instead of doing this:

[self.searchResults sortUsingSelector:@selector(compareByDeliveryTime:)];

you should do this:

SEL compareByDeliveryTimeSelector = sel_registerName("compareByDeliveryTime:");
[self.searchResults sortUsingSelector:compareByDeliveryTimeSelector];
Diamonddiamondback answered 20/9, 2013 at 15:7 Comment(6)
Thanks. This also eliminated a "The app references non-public selectors In Payload" warning I got during the submission process. After declaring the selector as laid out above, I was able to submit the app without any warnings.Scallop
Any idea why was the default build setting switched? What does calling sel_registerName (thus explicitly registering a method with the Objective-C runtime) buy you (besides the extra line)?Pingpingpong
It seems to me that this does not fix the warning, it simply hides it. Fixing it properly should involve including the file where the selector was declared, because then if that selector is renamed for some reason, the warning will reappear, which is what we should want.Bacciform
I think I remember reading something about this being required when the 64bit ARM stuff came in. I can't find the doc now though.Astilbe
There is some relevant stuff here: #7017781Astilbe
In Xcode 6, this merely transfers the warning to the second line and replaces it with PerformSelector may cause a leak because its selector is unknownMeakem
M
21

You just need to declare a class or protocol that contains the selector. For example:

//  DeliveryTimeComparison.h
#import <Foundation/Foundation.h>

@protocol DeliveryTimeComparison <NSObject>

- (void)compareByDeliveryTime:(id)otherTime;

@end

And then simply #import "DeliveryTimeComparison.h" in any class where you plan to use @selector(compareByDeliveryTime:).

Or alternatively, just import the class header for any object that contains a "compareByDeliveryTime:" method.

Momus answered 2/10, 2013 at 22:47 Comment(2)
I agree with the above method, because turning off warnings is not my preferred way of 'fixing'. With the appropriate header file and class/protocol names I'm able to find this documented 'quick-fix' easier. So for the time being I think I'll adopt Abhi's method.Hermaherman
This sounds fine unless you can't really include/import the class where the selector should be (cycle dependency problems, ..)Underwaist
S
15

Xcode 5 turned this on by default. To turn it off go to "Build Settings" for your target under "Apple LLVM 5.0 - Warnings - Objective C" -> "Undeclared Selector" set it to "NO". This should take care of it.

Sheedy answered 11/9, 2013 at 15:49 Comment(2)
this doesnt answer the question about how to fix the warning, instead prevents the warning from happening.. -1 for this!Diamonddiamondback
Agreed. But for those of us with bigger iOS 7 issues to resolve, this allows you to hide those until you can deal with them at a later time. And you'll have no issue submitting apps with these warnings.Sheedy
C
10

These selector warnings in MagicalRecord are for compatibility with mogenerator's generated Core Data classes. Besides using mogenerator and perhaps importing one of the entities there really isn't much you can do besides what was already answered.

Another option of course is to surround that code specifically with ignore blocks

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"

and at the end

#pragma clang diagnostic pop
Capps answered 3/4, 2014 at 0:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.