Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if NSString instance is contained in an NSArray

I have an array with a bunch of strings and I want to check if a certain string is contained in the array. If I use the containsObject: message on the array, I'm getting correct results. Do all NSString objects with the same string point to the same object? Or why is the containsObject: working?

NSArray *stringArray = [NSArray arrayWithObjects:@"1",@"2",@"3",anotherStringValue, nil]; if([stringArray containsObject:@"2"]){   //DO SOMETHING } 
like image 723
the Reverend Avatar asked Apr 27 '11 21:04

the Reverend


People also ask

Can NSArray contain nil?

arrays can't contain nil.

What is NSArray Objective-C?

The NSArray class contains a number of methods specifically designed to ease the creation and manipulation of arrays within Objective-C programs. Unlike some object oriented programming languages (C# being one example), the objects contained in an array do not all have to be of the same type.

Is NSArray ordered?

An object representing a static ordered collection, for use instead of an Array constant in cases that require reference semantics.


1 Answers

Yes, hard-coded NSStrings (string literals) (that is any @"..." in your source code) are turned into strings that exist indefinitely while your process is running.

However NSArray's containsObject: methods calls isEqual: on its objects, hence even a dynamically created string such as [NSString stringWithFormat:@"%d", 2] would return YES in your sample snippet.
This is because NSString's isEqual: (or more precisely its isEqualToString:) method is implemented to be content aware (vs. comparing pointer identities) and thus returns YES for any pair of strings containing the very same sequence of characters (at time of comparison), no matter how and when they were created.

To check for equal (pointer-)identity you'd have to enumerate your array and compare via

NSString *yourString = @"foo"; BOOL identicalStringFound = NO; for (NSString *someString in stringArray) {     if (someString == yourString) {         identicalStringFound = YES;         break;     } } 

(which you most likely wouldn't want, though).

Or in a more convenient fashion:

BOOL identicalStringFound = [stringArray indexOfObjectIdenticalTo:someString] != NSNotFound; 

(you most likely wouldn't want this one either).


Summing up:

So the reason you're getting a positive reply from containsObject: is NOT because literal strings share the same constant instance, BUT because containsObject: by convention calls isEqual:, which is content aware.

You might want to read the (short) documentation for isEqual: from the NSObject protocol.

like image 146
Regexident Avatar answered Oct 05 '22 00:10

Regexident