22

I have the NSMutableArray *children in the datastructure-class "Foo" which is the superclass of many others, like "Bar1" and "Bar2". That array stores Bar1 and Bar2 objects to get a tree-like recursive parent-children-structure of subclasses from Foo. To access the objects in the array, I loop through them using the foreach loop in Objective-C:

for(Foo *aFoo in children) {
    ...
}

But often I only need to loop through the objects in the array that have a certain class, in this case I want to perform a task for each object of the class Bar1 in the array children. Using for(Bar1 *anObject in children) again loops through ALL objects and not only the ones with the class Bar1. Is there a way to achieve what I need?

2 Answers 2

41

You have to loop over all objects and do a type check inside the loop.

for(id aFoo in children) {
    if ([aFoo isKindOfClass:[Bar1 class]])
        ...
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

this can be quite memory-expensive but apparently there's no other way. Thank You
no, it does not change your memory footprint, you are just reading what's already in memory
In general, if you need to use isKindOfClass: to differentiate between classes in a collection, your design pattern is outside the norm. This is particularly true if your collection contains instances of classes that are entirely of your creation.
14

You can do something like this:

NSPredicate* bar1Predicate = [NSPredicate predicateWithFormat:@"SELF.class == %@", [Bar1 class]];
NSArray* bar1z = [children filteredArrayUsingPredicate:bar1Predicate];
for(Bar1* bar in children) {
  // do something great
}

It's important to note, however, that this won't work with many standard Cocoa classes like NSString, NSNumber, etc. that use class clusters or special implementation classes (e.g., anything that is toll-free bridged with a CoreFoundation type) since the classes won't match exactly. However, this will work with classes you define as long as the class really is an instance of Bar1.

Emphasis Note: User @Alex suggested that it may not be clear that the classes must match exactly from my note above, so I am restating that. The classes must match exactly for this filter to work, so if you subclass Bar1 or provide some proxy class, you will have to adjust the filter in order for those classes to be included. As written, only instances of Bar1 will be returned in the filtered array.

6 Comments

also, I think this is not available on the iPhone
@unbeli: It is absolutely available on the iPhone, not that the OP mentioned the iPhone at all.
But, if you ever subclass Bar1, this code will not match objects of the subclass. The OP doesn't say anything about subclasses, but it's important to note.
@Jason Coco right, it's available, no idea why I remembered it wasn't.
@Alex: I was hoping that "since the classes won't match exactly" was enough, but I will edit it to add that more specifically as well.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.