Objective-C string comparison - objective-c

I have an array of names but can't seem to make the comparison work. Do I have an improper use of the language here?
NSLog(#"%#",[arrayOfNames objectAtIndex:0]);
if ([arrayOfNames objectAtIndex:0] == "Blue"){
NSLog(#"it's Blue");
}
else {
NSLog(#"it's not Blue");
}
The output is the following one:
Blue
it's not Blue

Use the following:
if ([[arrayOfNames objectAtIndex:0] isEqualToString:#"Blue"])
You're comparing two objects (one of the id-type, the other is a C-string) with the == operator. The comparison will fail, since they are 2 different objects. With the isEqualToString you are comparing the value of the object to the string #"Blue".

Related

Why a mutable copy of a NSString is said to be equal to the original immutable one?

Suppose I have a NSString* str1 and NSMutableString* str2, and I make str2 the mutable copy of str1. And I called the following method:
-(void)someMethod {
NSString *str1;
NSMutableString *str2;
str1 = #"OK";
str2 = [str1 mutableCopy];
if ([str2 isEqual:str1]) {
NSLog(#"Same!");
}
else {
NSLog(#"Not exactly!");
}
NSLog(#"%#", [[str1 class] description]);
NSLog(#"%#", [[str2 class] description]);
}
Console output:
2014-01-07 14:03:16.291 LearnFoundation[3739:303] Same!
2014-01-07 14:03:16.293 LearnFoundation[3739:303] __NSCFConstantString
2014-01-07 14:03:16.293 LearnFoundation[3739:303] __NSCFString
So here comes the confusion, according to the documentation of isEqual in NSString, it returns a Boolean value that indicates whether the receiver and a given object are equal. So why the mutable copy is said to be the same as the original immutable one?
Thanks in advance!
There are (at least) three separate concepts that can all be thought of as "equality":
"identity" (am I the same object as that other object?)
"equality" (am I exactly identical to this other object?)
"value equality" (do I have the same value as this other object?)
For ObjC objects you test for equal identities with ==, but equivalent values with isEqual:. There's no one-stop shop method for testing exact equality; it turns out to not be very useful, in general.
In Javascript (for comparison's sake), you test for equal identities with === and equivalent values with ==. There is similarly no direct way to test for exact equality.
For pass-by-value types like int and float, there's no such thing as identity, since you can't pass a particular instance around. However, if you squint a bit, you can think of this as being a similar case of different types with the same value:
int x = 5;
short y = 5;
if (x == y) {
...
}
Though in this case it's not a subtype relationship.
isEqual compares the contents of the two strings, not their types or identities. The contents are equal so it evaluates true.
To compare types, try:
if([str1 isKindOfClass:[str2 class]])
{
NSLog(#"same");
}else{
NSLog(#"different");
}
You should see "different" get logged.
They're equal as strings, but are distinct objects with distinct addresses. Thus, isEqual returns YES but a comparison with == would evaluate to NO.

How to best compare two NSString objects while ignoring case?

I want to compare two strings. It fails when the string have capital letter. How do I convert both string to capitalize and compare.
I have a sample code, can someone correct this.
if ([[txtAnswer.text capitalizedString] isEqualToString:[answer capitalizedString]]) {
// Do somehing
}
If you look at the NSString class reference you will see under the heading Identifying and Comparing Strings the methods caseInsensitiveCompare: and localizedCaseInsensitiveCompare:.
You might try something like:
if ([txtAnswer.text caseInsensitiveCompare: answer] == NSOrderedSame) {
// do something.
}
You can do a case insensitive string compare.
if([txtAnswer.text compare:answer options:NSCaseInsensitiveSearch] == NSOrderedSame)
{
// Do somehing
}

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.

String compare Objective-C

I've been struggling with a simple comparison but I can't get it to work.
I´m reading a XML file and I need to compare data from it in order to show the right picture.
http://www.cleaner.se/larm.xml (Example file for parsing)
I have tried things like:
if([aLarm.larmClass isEqualToString:#"A"])
NSLog(#"same");
else
NSLog(#"Not same");
If I use: NSLog(aLarm.larmClass); console puts it out nicely as it should. What am I doing wrong?
You can use the NSString compare: methods. For example:
if ([myString caseInsensitiveCompare:#"A"] == NSOrderedSame ) {
NSLog(#"The same");
} else {
NSLog(#"Not the same.");
}
The result is an NSComparisonResult which is just an enum with types NSOrderedSame, NSOrderedAscending and NSOrderedDescending.
Check the documentation on the various compare: methods here.
Of course, if the receiver is actually an NSString, then isEqualToString: should also work. So if you're trying to compare a class name (aLarm.larmClass ??), then you can call:
if ([NSStringFromClass([aLarm class]) isEqualToString:#"A"] ) {
NSLog(#"The same");
}
If the larmClass property is a string, make sure that it is actually one character in length (i.e. it doesn't have any leading or trailing whitespace that was accidentally included when parsing the XML). If the larmClass property truly is an NSString containing the letter ‘A’ then [aLarm.larmClass isEqualToString:#"A"] will return YES.
Do a:
NSLog(#"%u, %#", [aLarm.larmClass length], aLarm.larmClass);
and just make sure that it shows “1, A”.

Comparing Strings in Cocoa

I have tried:
- (NSString*) generateString
{
NSString* stringToReturn = #"thisString";
return stringToReturn;
}
- (void) otherMethod
{
NSString *returnedString = [self generateString];
if (returnedString == #"thisString")
{ // Do this }
else if (returnedString == #"thatString")
{ // Do that }
}
Which never matches.
I have then tried
if ([returnedString compare:#"thisString"] == 1)
But the compare method always returns 1 for me, even when comparing with a different string.
What is the correct way to do this, and what result should I expect?
First of all, you are using the == operator to compare two object pointers (of type NSString *). So that returns true when the pointers are the same, not when the strings have the same contents. If you wanted to compare whether two strings are the same, you should use isEqualToString: or isEqual: (isEqual: is more general as it works for all types of objects).
Second, compare: returns 0 (NSOrderSame) when they are the same, and 1 (NSOrderedDescending) when the first is greater than the second. So in fact it returns 1 only when they are different (specifically, when the first is greater than the second).
[returnedString isEqualToString: #"thisString"]
When comparing two identical strings compare will return NSOrderedSame, which is 0. It can also return NSOrderedAscending, -1, and NSOrderedDescending, 1.
You may prefer to use isEqualToString which returns YES or NO.
if ([returnedString isEqualToString:#"thisString"])
NSLog(#"Equal");
else
NSLog(#"Not Equal");
The == operator when applied to objects check whether the pointers are equal.
You have to use -compare method or one of its companions -compare:options: -compare:options:range: or -compare:options:range:locale: which return a NSComparisonResult (NSOrderAscending, NSOrderSame, NSOrderDescending)
If you just need equality comparison, you can use -isEqualToString: which returns a BOOL value.