Fixing "direct comparison of a string literal has undefined behavior" automatically - objective-c

In Xcode, I'm getting the error "direct comparison of a string literal has undefined behavior," and I know why I'm getting it, but is there some way for me to click a button and have Xcode remove it? I'm saying this because in 370 places in my app I've gotten it.

The clang option to disable this warning is -Wno-objc-literal-compare.
However, warnings are there for a reason; this one is because comparing against NSString literals using == is not guaranteed to behave as you might expect. Use isEqual: or isEqualToString: instead and you can both get rid of this warning and avoid having this turn into a bug for you later.

You can avoid the warning using `isEqualToString` instead of `==`.
`==` simply compares the pointers, which will usually be different even
if their contents are the same. The`isEqualToString` method compares
their contents.

Related

No warning when using nonnull?

With code like this:
- (nonnull NSString *)testing {
return nil;
}
Shouldn't I get a compiler warning? I get no warning all, which seems to make the entire nullability stuff seem useless?
Well, in my opinion it should produce a warning, but I couldn't figure out to get one either.
What might be helpful though, is using Product > Analyze to run the CLANG Static Analyzer. This should give the following hint:
Null is returned from a method that is expected to return a non-null value
Another thing worth mentioning is the setting CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION which is named Incorrect Uses of Nullable values in the Apple LLVM 7.1 - Warnings - All languages section of the Build Settings.
This setting will not produce a warning for incorrect return values, but it shows a warning when using the method with incorrect parameters (e.g. nil for nonnull parameters).
This answer refers to Xcode Version 7.3.1 (7D1014)
"nonnull" is mostly there to combine Objective-C and Swift. Swift will translate the type of the method to "NSString" and not "NSString?".

NSString isEqual strange bug

I have a web server which I used to fetch some data in my iOS application. The data include a field as the itemId let say '48501' (with no quotation). I read item JSON data into my itemObject in which itemId is defined as a NSString and not a NSInteger.
Everything works until this point but I have problems where I want to compare itemObject.itemId using isEqual: function with another NSString filled with 48501.
In other words both string are exactly the same and include 48501 when I print them. No space and hidden things is there. All isEqual: and isEqualToString: and == report false on comparison.
On the hand when I convert NSStrings to NSIntegers and compare them it works but not always! sometime TRUE sometime CRASH with no error to catch and just pointing to the line! I see them printed exactly the same but the if statement does not go through.
I showed the code to someone with far more experience than me and he was like this could be a bug! Anyone has ever exposed to this?
If your itemId is 48501 without any quotation in the JSON, then it's deserialized as NSNumber. Probably that's the problem in the first place. Try logging the type of your itemId and use appropriately -isEqualToString: for NSString and -isEqualToNumber: for NSNumber.

Objective-C, Buzztouch coding alerts - Data argument not used by format string and Semantic issue. Can someone explain what is going on?

I'm currently running Mountain Lion OS X 10.8 with Xcode 4.4 installed. I'm running the iOS 5.1 simulator. I'm using Buzztouch as a learning tool while I'm studying Objective-C and Xcode. I get the following alerts when I compile, but the build succeeds. However, I would like to know exactly what is going on and how I can remedy the situation. Thank you for any assistance you can provide. Here's the code and the alerts I'm getting:
BT_fileManager.m
Data argument not used by format string
[BT_debugger showIt:self:[NSString stringWithFormat:#"readTextFileFromBundleWithEncoding ERROR using encoding NSUTF8StringEncoding, trying NSISOLatin1StringEncoding", #""]];
Data argument not used by format string
[BT_debugger showIt:self:[NSString stringWithFormat:#"readTextFileFromCacheWithEncoding ERROR using encoding NSUTF8StringEncoding, trying NSISOLatin1StringEncoding", #""]];
BT_camera_email.m
Semantic Issue
Sending 'BT_camera_email *' to parameter of incompatible type 'id'
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
NSLog(#"is camera ok");
UIActionSheet *photoSourceSheet = [[UIActionSheet alloc] initWithTitle:#"Select Image Source"
delegate:self
Again, thanks.
Greg
I have no idea what Buzztouch might be, however.... :-)
The first warning is fairly simple. In a format string there are placeholders beginning with a '%' sign to indicate where data values should be substituted. For example, to substitute a string, one would use '%#'. In the examples you show, there are no placeholders but there are data values -- empty strings. The compiler is warning that something you indicate you want to have put into the new string created by stringWithFormat: won't be.
To be sure about the second one, I'd want to see the .h file that declares BT_camera_email but my best guess is that it doesn't adopt the UIActionSheetDelegate protocol. The description of initWithTitle:... says the second parameter should be id<UIActionSheetDelegate> and that's probably what is being complained about.

Remove "Format String is not a string literal" warning from xcode

When I use XCode I (obviously) put a bunch of NSLog statements in to keep track of some variables and method executions, etc. However, I keep getting this warning:
Format String is not a string literal (potentially insecure). I understand why this is here, but I also understand that it bugs the living crap out of me, especially when I have 20 or 30 of these warnings making it harder to track down real errors. Especially because everything in the string is defined by the system, not the user. Is there some way that I can disable this warning? Here's an example of a line that causes the warning.
NSLog([#"writeInfo " stringByAppendingString:[self saveFilePath:temp]]);
NSLog takes in a format string on its own, you do not need to inline create strings. In other words, you only need to write:
NSLog(#"writeInfo %#", [self saveFilePath:temp]);

Why do I need to cast before a method of an item of a NSArray can be called?

I am fairly new to Objective-C. Currently porting my own library from C#/Java to objective C.
I now run into a very strange problem for me.
I have a NSArray with several Note objects. I want to transpose on of these notes:
//Note.h
- (Note *) transpose: (int) semitones;
//Main
NSArray *notes = [get it from somewhere];
Note *transposedNote = [[notes objectAtIndex:0]transpose:1]; //Doesn't compile
Note *transposedNote = [(Note*)[notes objectAtIndex:0]transpose:1]//Does compile
Is this happening because there is already a transpose method available in the general libraries?
I thought due to the dynamic nature of objective-C at runtime it would be checked which class objectAtIndex returns and then sends the message to it?
It is my understanding that there is no runtime type checking for the assignment operator in Objective C. Since an array can contain a mixture of types, there is no way for the system to know what objectAtIndex returns.
How about
Note *transposedNote = [notes objectAtIndex:0]; // first line
[transposedNote transpose:1]; // second line
? Notice in the reference that objectAtIndex: returns an id, you will see it is pretty obvious:
In the code above, because id can fit into any object, the first line doesn't need to cast it into Note. In the second line I'm just calling a method on a Note so the compiler is happy.
In your code you are calling methods on the returned id object, so the compiler doesn't understand what you are trying to do. Just assign it to a Note reference and it will be fine.
Yes, the error is because there's already a transpose: method in AppKit. And you're also right that it normally doesn't cause an error when you have two unrelated classes implementing methods with the same name. The reason you get an error is because the two methods either return incompatible types or take incompatible types as arguments. In your particular case, you're seeing both problems:
-[NSResponder transpose:] takes an id and returns void
-[Note transpose:] takes an int and returns an id
These are totally incompatible types, and the compiler does need to know the types involved even if it doesn't know what exact method is going to be called.
It does compile unless you have -Werror set to treat warnings as errors.
It might produce a warning if the compiler doesn't already know about the selector or if the selector is declared in more than one class. In the former case, it should be necessary only to import the interface containing the selector. In the latter case, you'll need to do the cast to suppress the error.