Dan
Dan

Reputation: 233

How to check if an NSArray contains an object of a particular class?

What is the best way to test if an NSArray contains an object of a certain type of class? containsObject: seems to test for equality, whereas I'm looking for isKindOfClass: equality checking.

Upvotes: 20

Views: 13712

Answers (3)

Onato
Onato

Reputation: 10221

You can do this with an NSPredicate.

NSPredicate *p = [NSPredicate predicateWithFormat:@"self isKindOfClass: %@", 
                                                      [NSNumber class]];
NSArray *filtered = [identifiers filteredArrayUsingPredicate:p];
NSAssert(filtered.count == identifiers.count, 
         @"Identifiers can only contain NSNumbers.");

Upvotes: 11

Abizern
Abizern

Reputation: 150605

You could use blocks based enumeration to do this as well.

// This will eventually contain the index of the object.
// Initialize it to NSNotFound so you can check the results after the block has run.
__block NSInteger foundIndex = NSNotFound;

[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isKindOfClass:[MyClass class]]) {
        foundIndex = idx;
        // stop the enumeration
        *stop = YES;
    }
}];

if (foundIndex != NSNotFound) {
    // You've found the first object of that class in the array
}

If you have more than one object of this kind of class in your array, you'll have to tweak the example a bit, but this should give you an idea of what you can do.

An advantage of this over fast enumeration is that it allows you to also return the index of the object. Also if you used enumerateObjectsWithOptions:usingBlock: you could set options to search this concurrently, so you get threaded enumeration for free, or choose whether to search the array in reverse.

The block based API are more flexible. Although they look new and complicated, they are easy to pick up once you start using them - and then you start to see opportunities to use them everywhere.

Upvotes: 28

futureelite7
futureelite7

Reputation: 11502

You can use fast enumeration to loop through the array and check for the class:

BOOL containsClass = NO;

for (id object in array) {
    if ([object isKindOfClass:[MyClass class]]) {
         containsClass = YES;
         break;
    }
}

Upvotes: 7

Related Questions