2010-06-14 84 views
18

我有数据结构类“Foo”中的NSMutableArray *孩子,它是许多其他人的超类,如“Bar1”和“Bar2”。 该数组存储Bar1和Bar2对象以从Foo中获取类树的递归父子结构。 要使用foreach循环在Objective-C访问的对象数组中,我遍历他们:Objective-C NSMutableArray - 与多个类的对象的foreach循环

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

但是,我常常只能通过数组中有一定的类的对象需要循环,在这个case我想为数组子类中的类Bar1的每个对象执行任务。使用for(Bar1 *儿童中的anObject)会再次循环遍历所有对象,而不仅仅是具有Bar1类的对象。有没有办法实现我所需要的?

回答

40

您必须遍历所有对象并在循环内进行类型检查。

for(id aFoo in children) { 
    if ([aFoo isKindOfClass:[Bar1 class]]) 
     ... 
    } 
} 
+1

这可能相当昂贵,但显然没有别的办法。谢谢 – 2010-06-14 13:57:01

+5

不,它不会改变你的内存占用量,你只是在读内存中已有的内容 – unbeli 2010-06-14 14:02:11

+3

一般来说,如果你需要使用'isKindOfClass:'来区分集合中的类,你的设计模式就超出了规范。如果您的集合包含完全由您创建的类的实例,则尤其如此。 – bbum 2010-06-14 16:50:42

9

你可以做这样的事情:

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

它然而,必须指出的是,这不会有很多标准Cocoa类一样的NSString,NSNumber的,等使用类集群的工作是非常重要的或特殊实现类(例如,任何与CoreFoundation类型桥接的免费),因为这些类不会完全匹配。但是,只要该类真的是Bar1的实​​例,就可以与您定义的类一起工作。

强调说明:User @ Alex建议,可能不清楚这些类必须完全匹配上面的注释,所以我重申了这一点。这些类必须完全匹配才能使此过滤器起作用,因此如果您继承Bar1或提供一些代理类,则必须调整过滤器才能包含这些类。正如所写,只有Bar1的实例将被返回到已过滤的数组中。

+0

另外,我认为这不适用于iphone – unbeli 2010-06-14 14:02:38

+2

@unbeli:它绝对可用在iPhone上,而不是OP提到iPhone。 – 2010-06-14 14:04:02

+0

但是,如果您曾经继承过Bar1,那么这段代码将不会匹配子类的对象。 OP没有提到有关子类的任何内容,但需要注意的重要。 – Alex 2010-06-14 14:12:36