2010-06-14 21 views
18

Tengo los hijos NSMutableArray * en la clase de estructura de datos "Foo" que es la superclase de muchos otros, como "Bar1" y "Bar2". Esa matriz almacena objetos Bar1 y Bar2 para obtener una estructura padres-hijos-recursiva similar a un árbol de las subclases de Foo. Para acceder a los objetos de la matriz, que bucle a través de ellos mediante el bucle foreach en Objective-C:Objective-C NSMutableArray - bucle foreach con objetos de múltiples clases

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

Pero a menudo sólo tienen que recorrer los objetos de la matriz que tienen una determinada clase, en este caso quiero realizar una tarea para cada objeto de la clase Bar1 en la matriz niños. El uso de for (Bar1 * anObject in children) vuelve a recorrer todos los objetos y no solo los que tienen la clase Bar1. ¿Hay alguna manera de lograr lo que necesito?

Respuesta

40

Tiene que recorrer todos los objetos y hacer una comprobación de tipo dentro del ciclo.

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

esto puede ser bastante caro para la memoria, pero aparentemente no hay otra manera. Gracias –

+5

no, no cambia la huella de su memoria, solo está leyendo lo que ya está en la memoria – unbeli

+3

En general, si necesita usar 'isKindOfClass:' para diferenciar entre clases en una colección, su patrón de diseño está fuera de la norma. Esto es particularmente cierto si su colección contiene instancias de clases que son completamente de su creación. – bbum

9

Usted puede hacer algo como esto:

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

Es importante señalar, sin embargo, que esto no funcionará con muchas clases de cacao estándar como NSString, NSNumber, etc., que utilizan grupos de clase o clases de implementación especiales (p. ej., todo lo que es un puente gratuito con un tipo de CoreFoundation) ya que las clases no coincidirán exactamente. Sin embargo, esto funcionará con las clases que defina siempre que la clase realmente sea una instancia de Bar1.

Nota de énfasis: El usuario @Alex sugirió que puede no estar claro que las clases deben coincidir exactamente con mi nota anterior, por lo que estoy reiterando eso. Las clases deben coincidir exactamente para que este filtro funcione, por lo que si subclase Bar1 o proporcione alguna clase de proxy, tendrá que ajustar el filtro para que se incluyan esas clases. Tal como está escrito, solo se devolverán instancias de Bar1 en la matriz filtrada.

+0

también, creo que esto no está disponible en el iPhone – unbeli

+2

@unbeli: Está absolutamente disponible en el iPhone, no es que el OP haya mencionado el iPhone en absoluto. –

+0

Pero, si alguna vez subclases 'Bar1', este código no coincidirá con los objetos de la subclase. El OP no dice nada sobre las subclases, pero es importante tener en cuenta. – Alex