40

I have a NSMutableArray which contains a few NSString objects. How can I test if the array contains a particular string literal?

I tried [array containsObject:@"teststring"] but that doesn't work.

mmmmmm
  • 32,227
  • 27
  • 88
  • 117
tech74
  • 1,355
  • 3
  • 21
  • 35

5 Answers5

87

What you're doing should work fine. For example

NSArray *a = [NSArray arrayWithObjects:@"Foo", @"Bar", @"Baz", nil];
NSLog(@"At index %i", [a indexOfObject:@"Bar"]);

Correctly logs "At index 1" for me. Two possible foibles:

  1. indexOfObject sends isEqual messages to do the comparison - you've not replaced this method in a category?
  2. Make sure you're testing against NSNotFound for failure to locate, and not (say) 0.
Adam Wright
  • 48,938
  • 12
  • 131
  • 152
  • It will not work in certain cases because it checks reference. – Stoto Jun 11 '12 at 10:05
  • 5
    @Stoto It does not check references. It uses `-isEqual:` as the answer describes. – Mike Weller Jun 11 '12 at 10:15
  • 1
    LOL! @Stoto it sounds like you've been reading this thread https://devforums.apple.com/thread/168948?start=0&tstart=0 – Fogmeister Oct 03 '12 at 12:53
  • Yes, i did :) I am sure it checks reference, but due to compiler optimization two @"Bar" string constants are basically one String (pointers pointing to the same data) – Stoto Oct 04 '12 at 13:47
  • 3
    For the record, I tested this option and it works perfectly. Apple's reference at https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html explicitly states that `isEqual:` is used for comparisons. On `NSString` objects, `isEqual:` tests the contents of the strings. – Aaron Mar 22 '13 at 16:04
78
[array indexOfObject:object] != NSNotFound
Şafak Gezer
  • 3,928
  • 3
  • 47
  • 49
Bogdan
  • 2,608
  • 2
  • 27
  • 26
8

Comparing against string literals only works in code examples. In the real world you often need to compare against NSString* instances in e.g. an array, in which case containsObject fails because it compares against the object, not the value.

You could add a category to your implementation which extends NS(Mutable)Array with a method to check wether it contains the string (or whatever other type you need to compare against);

@implementation NSMutableArray (ContainsString)
-(BOOL) containsString:(NSString*)string
{
  for (NSString* str in self) {
    if ([str isEqualToString:string])
      return YES;
  }
  return NO; 
}
@end
Henrik Hartz
  • 3,677
  • 1
  • 27
  • 28
  • 1
    I don't think this is true. Apple's docs for [`containsObject`](https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/index.html#//apple_ref/occ/instm/NSArray/containsObject:) and [`indexOfObject`](https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/index.html#//apple_ref/occ/instm/NSArray/indexOfObject:) both say each element is sent an `isEqual:` message, so it should work even when two different NSString objects contain the same character content. – peterflynn Jun 24 '15 at 18:45
  • that is only true if both objects are NSString – Henrik Hartz Jun 25 '15 at 07:13
6

You may also use a predicate:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", theArray];
BOOL result = [predicate evaluateWithObject:theString];
j0k
  • 22,600
  • 28
  • 79
  • 90
Bruno
  • 101
  • 1
  • 1
5

for every object

[(NSString *) [array objectAtIndex:i] isEqualToString:@"teststring"];
Mihir Mehta
  • 13,743
  • 3
  • 64
  • 88
  • 16
    I downvoted because it's *not* the right answer. You don't need to manually iterate over the array, because indexOfObject works fine. This answer will always be slower (sending many messages, no access to internal representations), and far more cumbersome. I only downvote answers when I have myself posted another answer when it's unambiguously wrong. – Adam Wright Apr 23 '10 at 10:49
  • 6
    I think this is correct if the strings are not static. Equality works for static strings, but not for dynamically allocated ones. – bbrame May 05 '11 at 13:58
  • 4
    It may not be the accepted answered, but its still a valid answer. I dont think down voting it was appropriate – AlBeebe Oct 12 '11 at 20:33
  • 1
    The accepted answer is wrong because First of all it checks the reference which can be the same if you have string constant like in the example, but will not work if the same string will be created dynamically (coming from file, web, ...) Second, there is a containsObject: method for the same thing, so you shouldn't use indexOfObject: for this. Therefore this is the correct answer. – Stoto Jun 11 '12 at 10:04
  • I adapted this in a fast enumeration loop - as a part of HTML processing using the HPPLE library. I wanted to compare the content of the
    - looking for a specific string.
    – Ashu Joshi Aug 17 '12 at 04:16
  • it's simply wrong. the correct answer is to use indexOfObject: – Pavel Aug 25 '13 at 10:54
  • 1
    it's simply wrong to use indexOfObject, this is the correct answer. – Fattie Aug 16 '15 at 03:39