web-dev-qa-db-ja.com

Objective-C NSMutableArray-複数のクラスのオブジェクトを持つforeachループ

NSMutableArray * childrenは、 "Bar1"や "Bar2"など、他の多くのスーパークラスであるdatastructure-class "Foo"にあります。その配列はBar1およびBar2オブジェクトを格納して、Fooからサブクラスのツリーのような再帰的な親子構造を取得します。配列内のオブジェクトにアクセスするには、Objective-Cのforeachループを使用してループします。

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

しかし、多くの場合、特定のクラスを持つ配列内のオブジェクトをループするだけでよく、この場合、配列の子のクラスBar1の各オブジェクトに対してタスクを実行します。 for(Bar1 * anObject in children)を再び使用すると、クラスBar1のオブジェクトだけでなく、すべてのオブジェクトがループされます。私が必要とするものを達成する方法はありますか?

20
Nils Fischer

すべてのオブジェクトをループし、ループ内で型チェックを行う必要があります。

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

あなたはこのようなことをすることができます:

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

ただし、これはNSStringやNSNumberなど、クラスクラスターまたは特別な実装クラス(たとえば、CoreFoundation型でフリーブリッジされているもの)を使用する多くの標準Cocoaクラスでは機能しないことに注意することが重要です。クラスは完全には一致しません。ただし、クラスが本当にBar1のインスタンスである限り、これは定義したクラスで機能します。

Emphasis Note:ユーザー@Alexは、クラスが上記の私のメモから正確に一致する必要があることは明確ではない可能性があることを示唆したので、それを再言します。このフィルターが機能するには、クラスが完全に一致する必要があります。そのため、Bar1をサブクラス化するか、プロキシクラスを提供する場合、これらのクラスが含まれるようにフィルターを調整する必要があります。書かれているように、onlyBar1のインスタンスは、フィルタリングされた配列で返されます。

12
Jason Coco