Should I fix Xcode 5 'Semantic issue: undeclared selector'? - ios

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?!

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];

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.

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.

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

Related

Strange Clang behaviour in Xcode 8.3

Recently i noticed strange behaviour with Objective C memory management in Xcode.
Here is the code:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSString *firstString = [[NSString alloc] initWithString: #"Hello"];
NSString *secondString = firstString;
[firstString release];
NSLog(#"%#", secondString);
}
return 0;
}
I think, that secondString points to nil after releasing firstString and NSLog should produce error.
But this code does not produce any errors and successfully prints "Hello" string.
I manually compiled and run code with such command and does not noticed any errors too:
% clang -framework Foundation -fno-objc-arc main.m && ./a.out
I tried to compile this code with online objective-c compiler (GCC) (http://rextester.com/l/objectivec_online_compiler) and error was occurred.
What am i doing wrong?
ARC support is turned off in Xcode.
Thanks in advance.
If you perform a static analysis (shift+command+B in Xcode, or "Analyze" on Xcode's "Product" menu), it will warn you that you're trying to reference an object after it is released:
The issue is that in manual reference counting code, your references to deallocated objects are not set to nil automatically. So you can end up with dangling pointers to an object that was previously deallocated unless you manually nil those pointers.
The static analyzer is remarkably good at identifying these sorts of issues, amongst others. I would advise making sure you have a clean bill of health from the static analyzer before moving on.
The second line of defense in situations like this is to enable the zombies runtime debugging option. This will report any attempts to interact with objects after they've been deallocated. Zombies can be enabled in the "Diagnostics" section when you edit your Xcode target's scheme.
Unfortunately, you are using NSString, which doesn't follow the typical memory management rules (it can keep its own references to strings, so they're not always deallocated when you'd otherwise expect them to be).
Consider an example similar to yours, except with a custom class:
#import <Foundation/Foundation.h>
#interface MyObject: NSObject
#end
#implementation MyObject
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
MyObject *firstObject = [[MyObject alloc] init];
MyObject *secondObject = firstObject;
[firstObject release];
NSLog(#"%#", secondObject);
}
return 0;
}
If you run this with zombies on, you'll get a corresponding error message indicating that you're trying to interact with a deallocated instance:
2017-05-27 08:19:18.154033-0700 MyApp[36888:7215135] *** -[MyObject isProxy]: message sent to deallocated instance 0x100303620
But you may not get this warning from NSString. Bottom line, one should avoid drawing any broader memory management conclusions from NSString behavior. Instead, rely upon Xcode's static analyzer and zombies. (Note, remember to turn off zombies when you're done debugging your app.)

Duplicate symbol error with GoogleCast.framework

I just started porting an Android app to iOS, and am hitting a major roadblock that I can't figure out despite scouring many similar questions.
I am attempting to follow the pattern implemented in the CastVideos sample where the GoogleCast API is encapsulated in a singleton class which I've called CastManager. To use my singleton class, I #import "CastManager.h" in AppDelegate.m. Then in CastManager.h, I #import <GoogleCast/GoogleCast.h> so that I can use classes and protocols from it as part of CastManager's public interface. However, because I'm importing CastManager.h in both CastManager.m and AppDelegate.m, the linker is finding duplicate symbols from the GoogleCast framework.
This is my CastManager.h:
#import <GoogleCast/GoogleCast.h>
#import <Foundation/Foundation.h>
#interface CastManager : NSObject
#property(nonatomic, strong) GCKDeviceScanner *deviceScanner;
+ (instancetype)sharedCastManager;
#end
And corresponding CastManager.m:
#import "CastManager.h"
#implementation CastManager
+ (instancetype)sharedCastManager {
NSLog(#"sharedCastManager");
static CastManager *singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[self alloc] init];
});
return singleton;
}
- (instancetype)init {
NSLog(#"init()");
if (self = [super init]) {
self.deviceScanner = [[GCKDeviceScanner alloc] init];
}
return self;
}
#end
And this is the main part of my AppDelegate.m:
#import "AppDelegate.h"
#import "CastManager.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CastManager *castManager = [CastManager sharedCastManager];
return YES;
}
However, this results in the following error from the linker when attempting to build the project:
duplicate symbol _kGCKDeviceCapabilityVideoOut in:
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/AppDelegate.o
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/CastManager.o
... many similar errors ommitted for brevity ...
duplicate symbol _kGCKDeviceCapabilityAudioIn in:
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/AppDelegate.o
/Users/nate/Projects/MyCastApp/GoogleCast.framework/GoogleCast(GCKDevice.o)
ld: 8 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
As far as I can tell, this exactly copies the pattern as defined in the CastVideos sample, but the sample compiles fine, and mine doesn't, and I've scoured through both projects trying to find what is different, but I just don't see it. Further, I don't see anything really wrong with doing this, and would expect it to work fine. I can't think of any other way to do it, really.
Here are the relevant files from the CastVideos sample for comparison:
ChromecastDeviceController.h
ChromecastDeviceController.m
AppDelegate.m
Other questions point to solutions that don't apply or don't fix it:
I'm not importing a .m file on accident.
I don't have duplicate references to any files in the project.
The "Compile Sources" section of the "Build Phases" project setting doesn't include any duplicates.
I've added the '-ObjC' linker flag as described by the GoogleCast API docs, though it has the same error with or without it.
I've tried deleting the delegate data and doing a clean before building.
This is with Xcode 6.3.1 running on OS X Yosemite 10.10.3 and the GoogleCastSDK-2.6.0 package from the SDK documentation page
I have checked in my sample project with the problem at https://github.com/nshafer/MyCastApp
Any help is greatly appreciated!
Edit: the duplicate is somewhat related, it's definitely about the same symbols, but the answers there didn't help, as I'm not using Object-C++, but rather just Objective-C. I don't have a .mm file, just a .m file.
For me it helped to switch the "No Common Blocks" compiler setting to NO:
It pretty much seems to make sense, the setting is explained here: What is GCC_NO_COMMON_BLOCKS used for?
The linker tells you that you have a variable named kGCKDeviceCapabilityVideoOut in two files, AppDelegate.m and CastManager.m. Since it's not in your source code, it's most likely in the GoogleCast code that you are including.
Either change the GoogleCast.h file, or make sure it is only included in one .m file. Including it from CastManager.h means it is indirectly included in every file that includes CastManager.h, so I would avoid that and only include it from CastManager.m. You'll probably have to add
#class GCKDeviceScanner;
in your CastManager.h file.
I found another fix, which is to edit GCKDevice.h in the GoogleCast.framework/Headers folder. Change the 4 constants from GCK_EXPORT to GCK_EXTERN near the top of the file.
/** Device capability flag for video out. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityVideoOut;
/** Device capability flag for video in. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityVideoIn;
/** Device capability flag for audio out. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityAudioOut;
/** Device capability flag for audio in. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityAudioIn;
I detailed this in a bug report I filed with Google's issue tracker, but it was marked as a duplicate of another somewhat related issue. Either way, it will perhaps get fixed in the next version. Until then, I would suggest going with changing the "No Common Blocks" setting as detailed in Joobik'com's answer, as that doesn't involve changing the 3rd party code.

iTunes Store Operation failed - the app references non-public [duplicate]

I am getting this warning while submitting app to the Apps store through organizer.
The app references non-public selectors in Payload/.app/: decoder
i know we get this warning if we use any Third Party API in our application. I have used SOCKETIO-ObjC library for chat functionality in application. Also used facebook iOS sdk for fb implementation.So i am not getting exactly what causes this warning.! Please find attached ScreenShot for better understanding
You may get this warning just for using a selector in your own code or third party code that has the same name as some selector that is marked as non-public. Happens to me all the time. Never got rejected for it.
By "same name" i mean just something as simple as you having an object with this selector:
-(id) XYZKMyClass doSomethingFancy:(id) toThis
...and there being a selector like this for an internal Apple functionality
-(id) ApplesClass doSomethingFancy:(id) toSomething
So: What it seems they are looking for is the signature -(id) doSomethingFancy:(id). You can see how it's very easy to accidentally bump up against this.
Presumably they perform a deeper check at the App Store Police HQ, and determine that the flagged selector is in your code, and hence OK.
This can help you:
Before:
#import "SocketIOJSONSerialization.h"
extern NSString * const SocketIOException;
// covers the methods in SBJson and JSONKit
#interface NSObject (SocketIOJSONSerialization)
// used by both JSONKit and SBJson
- (id) objectWithData:(NSData *)data;
// Use by JSONKit serialization
- (NSString *) JSONString;
**- (id) decoder;**
// Used by SBJsonWriter
- (NSString *) stringWithObject:(id)object;
#end
After:
#import "SocketIOJSONSerialization.h"
extern NSString * const SocketIOException;
// covers the methods in SBJson and JSONKit
#interface NSObject (SocketIOJSONSerialization)
// used by both JSONKit and SBJson
- (id) objectWithData:(NSData *)data;
// Use by JSONKit serialization
- (NSString *) JSONString;
**- (id) jsonDecoder;**
// Used by SBJsonWriter
- (NSString *) stringWithObject:(id)object;
#end
I get in this link: http://blog.csdn.net/erica_sadun/article/details/12188083
Check your Target Membership for all classes used in project. In some cases when you create or copy your target the warning may appears without link error.

Return statement will never be executed warning

I've recently come across with double return statement (one of them was added by mistake) in our project and wondering why compiler doesn't show a warning for that?!
Ok, I added -Wunreachable-code to other warning flags, but still no luck.
Got warning - with a code to execute after return statement:
Didn't get warning but still second return statement will never be executed.
Even if I add something like this, still no warning
Is there extra warning flag for that, or compiler isn't smart enough?
Good catch!
-Wunreachable-code does not report a warning and there is no other warning flag which would do.
Not even the Static Analyzer catches this mistake!
(Tested with XCode 6.1 GM 2)
Wrap your code in pragma flags that will suppress that warning between the push and pop
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunreachable-code"
//Your code goes here
#pragma GCC diagnostic pop
Use -Wno-unreachable-code for your file in Build Phases.
Try this...
-(NSString*) makeSomeStringForMe {
NSString *someString = #"some string";
return someString;
}

suppressing "incompatible pointer types sending 'subclassA' to parameter of type 'subclassB' " clang

Xcode raising "incompatible pointer types sending 'subclassA' to parameter of type 'subclassB' " warning. Compiling with clang.
In the case where the warning is raised, I use a
[subclassA isKindOfClass: [subclassB class]] ...
to ensure compatible pointer use. I'd like something like:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
// warning-raising code
#pragma clang diagnostic pop
but for the appropriate warning raised. I.e. Whats the clang flag to ignore the specified diagnostic?
Thanks for your time.
If I understand you right, you're saying something like
if ([subclassA isKindOfClass:[subclassB class]]) {
[foo someMethodThatWantsSubclassB:subclassA];
}
The fix here is to cast subclassA after the successful type assertion. Your case is a bit odd in that you're dynamically determining the type of subclassB instead of testing for a static type, but in the method -someMethodThatWantsSubclassB: you definitely know the type involved, so you'd write something like
if ([subclassA isKindOfClass:[subclassB class]]) {
[foo someMethodThatWantsSubclassB:(BClass)subclassA];
}
If you have some really weird setup where you don't actually know the static type of subclassB (although I can't imagine the situation here) you could simply cast to (id) instead to get rid of the warning:
if ([subclassA isKindOfClass:[subclassB class]]) {
[foo someMethodThatWantsSubclassB:(id)subclassA];
}

Resources