NSString comparison question - objective-c

I am trying to test to see if an NSString has the letters "PDF" as the first 3 letters:
if ([[[profiles stringForKey:#"response"] characterAtIndex:0] isEqualToString:#"P"]) {
//TODO
}
I started with this approach to see if I could at least narrow it down to those strings that start with "P" but I am getting an error on this that reads: "Invalid receiver type 'unichar'" AND "Cast to pointer from integer of different size"
Am I getting these errors because I am using the isEqualToString comparison? Does that attach the terminating zero to "P"? I tried to use the "==" comparison but I was also getting an error with that method.

if ([profiles hasPrefix:#"PDF"]) {
NSLog(#"my string starts with \"PDF\"");
}

You want to use the method substringToIndex instead of characterAtIndex. characterAtIndex is returning a unichar which is not an objective-c object to which isEqualToString can be sent.
Here is something that worked for me:
NSString* testString = #"PDFDocument";
NSString* subString = [testString substringToIndex:3];
if ( [subString isEqualToString:#"PDF"] == YES )
{
NSLog( #"same" );
}

Related

Extremely simple -- how to compare chars

I shouldn't be struggling this much. I want to extract a character from a string and compare it to a char. Here's the offending line:
if ([url characterAtIndex:url.length - 4] == "=") {
NSString *test = [url substringFromIndex:url.length - 3];
return [test intValue];
} else {
NSString *test = [url substringFromIndex:url.length - 2];
return [test intValue];
}
On the if line it throws the error Comparison between pointer and integer ('int' and 'char *'), strange enough on it's own since there isn't a single int in that comparison.
A second error also pops, Result of comparison against string literal is unspecified (use strncmp instead).
I'd love help with this error, I have no idea why it's getting thrown and it's stopping me from getting to the real work of debugging network calls. Any help is greatly appreciated!
Change "=" to '='.
"=" is a C string.
'=' is a char.
BTW - characterAtIndex: returns a unichar which is an unsigned short.

Getting "Array element cannot be nil" from Analyzer as a false-positive

I have a case where the XCode analyzer is flagging valid code.
We have an NSString category with a method isEmpty which checks if the string is empty, including checking for a nil string. When it's used in combination with adding the string to an array, the analyzer complains:
if (![NSString isEmpty:myString]) {
[_myArray addObject:myString];
}
The analyzer will then complain with Array element cannot be nil, because it isn't smart enough to detect that isEmpty is preventing that.
What's the best workaround? I know I can change the condition to if (myString && ![NSString isEmpty... but that seems like a clunky workaround.
EDIT: By request, here's the body of isEmpty:
+ (BOOL)isEmpty:(NSString *)string
{
return (string ? [string isEqualToString:#""] : YES);
}
You're correct that you have to show the analyzer every possible logical path. Your "workaround" is perfectly good.
It might be that your isEmpty could be written to help the analyzer more, but you didn't show that, so it's impossible to say. Based on what you've actually shown, I would suggest that you just use your "workaround" and move on.
In Objective-C the easiest way to check for non-nil and non-empty for NSString is to get the length. It returns 0 for nil and empty and the proper length for non-empty.
NSString *testNil = nil;
NSString *testEmpty = #"";
NSString *testNonEmpty = #"Hello";
NSInteger testNilLength = [testNil length]; // -> 0
NSInteger testEmptyLength = [testEmpty length]; // -> 0
NSInteger testNonEmptyLength = [testNonEmpty length]; // -> 5

How to check if NSString returned by objectForKey is "" objective c

I'm not exactly sure how to check whether a NSString is blank or not, I've got this code...
NSString *imageName = [myItem objectForKey:#"iconName"];
if(imageName == #"")
{
}
And when I do a print on the myItem object, it comes up as..
iconName = "";
At the NSString *imageName line, I noticed in xcode in the console it says
"variable is not NSString"
Which I don't get as iconName is saved and stored on the parse.com database as a NSString.
When I run that code though it doesn't seem to realise that imageName = "";
You should use this code block when comparing strings:
if ([imageName isEqualToString:#""]){
}
You need to use isEqualToString to compare two strings. If you just use == then you are comparing two pointers.
You could also check to see if the object you are receiving is a NSString by:
if ([imageName isKindOfClass:[NSString class]])
Hope this helps.
Although you have a few answers already, here is my take.
First of all, your warning (not error) can be fixed like this:
NSString *imageName = (NSString *)[myItem objectForKey:#"iconName"];
Then, I would check to make sure that the string is not nil and that it is not blank. The easiest way to do this in objective-C is to check the length of the string, since if it nil it will return 0, and if it is empty, it will return 0:
if([imageName length] == 0)
{
// This is an empty string.
}
As #jlehr points out, if there is the possibility that imageName may not actually be stored as a string, then in order to prevent a crash you need to check first. (This may or may not be needed, depending on the logic of your application):
if ([imageName isKindOfClass:[NSString class]]
{
if([imageName length] == 0)
{
// This is an empty string.
}
}
The "variable is not NSString" is probably because objectForKey: return an id.
To should use [imageName isEqualToString:#""].

Objective-C NSString for loop with characterAtIndex

I'm trying to loop through a NSString, character by character, but I'm getting a EXC_BAD_ACCESS error. Do you have an idea how to do this right? I've been googling for hours now but can't figure it out.
Here is my code (.m):
self.textLength = [self.text length];
for (int position=0; position < self.textLength; position++) {
NSLog(#"%#", [self.text characterAtIndex:position]);
if ([[self.text characterAtIndex:position] isEqualToString:#"."]){
NSLog(#"it's a .");
}
}
Thanks a lot!
Characters are not object. characterAtIndex returns unichar, which is actually an integer type unsigned short. You need to use %C instead of %# in NSLog. Also character is not a NSString, so you can't send it isEqualToString. You need to use ch == '.' to compare ch against '.'.
unichar ch = [self.text characterAtIndex:position];
NSLog(#"%C", ch);
if (ch == '.') {} // single quotes around dot, not double quotes
Note that, 'a' is character, "a" is C string and #"a" is NSString. They all are different types.
When you are using %# with unichar ch in NSLog, it is trying to print an object from memory location ch which is invalid. Thus you are getting a EXC_BAD_ACCESS.
characterAtIndex: returns a unichar, so you should use NSLog(#"%C", ...) instead of #"%#".
You also cannot use isEqualToString for a unichar, just use == '.' is fine.
If you want to find the position of all '.'s, you can use rangeOfString. Refer to:
String Programming Guide: Searching, Comparing, and Sorting Strings
Position of a character in a NSString or NSMutableString
characterAtIndex: returns a unichar, which is declared as typedef unsigned short unichar; The format specifier you are using in your calls to NSLog are incorrect, you could just do NSLog(#"%u",[self.text characterAtIndex:position]); or NSLog(#"%C",[self.text characterAtIndex:position]); if you want the actual character to print out.
Also, as a result of unichar being defined the way that it is, it's not a string, so you cannot compare it to other strings. Try something like:
unichar textCharacter = '.';
if ([self.text characterAtPosition:position] == testCharacter) {
// do stuff
}
If you want to find the location of a character in a string you can use this:
NSUInteger position = [text rangeOfString:#"."].location;
if the character or text is not found you will get a NSNotFound:
if(position==NSNotFound)
NSLog(#"text not found!");

Converting NSNumber to NSString is not realy a string

I have got a problem with converting an NSNumber value to an NSString
MyPowerOnOrNot is an NSNumber witch can only return a 1 or 0
and myString is an NSString..
myString = [NSString stringWithFormat:#"%d", [myPowerOnOrNot stringValue]];
NSLog(#"%#",myString);
if(myString == #"1") {
[tablearrayPOWERSTATUS addObject:[NSString stringWithFormat:#"%#",#"ON"]];
}
else if(myString == #"0") {
[tablearrayPOWERSTATUS addObject:[NSString stringWithFormat:#"%#",#"OFF"]];
}
What is wrong with this?
The NSLog shows 0 or 1 in the console as a string but I can't check it if it is 1 or 0 in an if statement?
If doesn't jump into the statements when it actually should.. I really don't understand why this doesn't works..
Any help would be very nice!
A couple of problems
myString = [NSString stringWithFormat:#"%d", [myPowerOnOrNot stringValue]];
-stringValue sent to an NSNumber gives you a reference to a string. The format specifier %d is for the C int type. What would happen in this case is that myString would contain the address of the NSString returned by [myPowerOnOrNot stringValue]. Or, on 64 bit, it would return half of that address. You could actually use [myPowerOnOrNot stringValue] directly and avoid the relatively expensive -stringWithFormat:
if(myString == #"1")
myString and #"1" are not necessarily the same object. Your condition only checks that the references are identical. In general with Objective-C you should use -isEqual: for equality of objects, but as we know these are strings, you can use -isEqualToString:
if ([[myPowerOnOrNot stringValue] isEqualToString: #"1"])
Or even better, do a numeric comparison of your NSNumber converted to an int.
if ([myPowerOnOrNot intValue] == 1)
Finally if myPowerOnOrNot is not supposed to have any value other than 0 or 1, consider having a catchall else that asserts or throws an exception just in case myPowerOnOrNot accidentally gets set wrong by a bug.
"myString " is a reference to a string, not the value of the string itself.
The == operator will compare the reference to your string literal and so never return true.
Instead use
if( [myString isEqualToString:#"1"] )
This will compare the value of myString to "1"
In Objective C; you can't compare strings for equality using the == operator.
What you want to do here is as follows:
[tablearrayPOWERSTATUS addObject:([myPowerOnOrNot integerValue]?#"ON":#"OFF"])];
Compact, fast, delicious.