Reputation: 233
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
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
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
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