¿Hay alguna manera de construir un predicado para filtrar por tipo de clase?¿Es posible filtrar un NSArray por clase?
Actualmente recorro la matriz y compruebo la clase de cada objeto. Tal vez hay una manera más limpia?
¿Hay alguna manera de construir un predicado para filtrar por tipo de clase?¿Es posible filtrar un NSArray por clase?
Actualmente recorro la matriz y compruebo la clase de cada objeto. Tal vez hay una manera más limpia?
Se podría añadir una categoría para NSObject que añade un método "cf_className", así:
@interface NSObject (CFAdditions)
- (NSString *) cf_className;
@end
@implementation NSObject (CFAdditions)
- (NSString *) cf_className {
return NSStringFromClass([self class]);
}
@end
A partir de ahí, se puede utilizar como predicados:
NSPredicate * p = [NSPredicate predicateWithFormat:@"cf_className = %@", aClass];
NSArray * filtered = [anArray filteredArrayUsingPredicate:p];
Si estás en Mac, puede usar -[NSObject className]
en lugar de tener que crear la categoría. El iPhone no tiene ese método, de ahí la necesidad de una categoría.
También puede hacer self.class.description –
@BrianKing excelente punto –
Puede comparar clases directamente en su predicado.
Pero, probablemente no funcione como es de esperar si está tratando de filtrar objetos que pertenecen a grupos de clases o si tiene subclases.
Por ejemplo, cuando se crea una instancia NSDate
es por lo general un __NSCFDate
y NSString
puede ser NSCFString
, así como otras clases privadas específicas.
Probablemente sea mejor simplemente recorrer el conjunto usted mismo y usar -isKindOfClass:
como prueba.
SI que realmente desea utilizar NSPredicate
aunque se puede hacer esto. Como ejemplo, esto filtraría una matriz para todos los objetos derivados de NSString
. Si desea una membresía de clase estricta, puede reemplazar isKindOfClass:
con isMemberOfClass:
.
Cualquier selector que implementen todos los objetos de la colección, toma un argumento y devuelve un BOOL
debería funcionar.
NSArray *mixedArray = {...};
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"self isKindOfClass: %@",
[NSString class]];
NSLog(@"%@", [mixedArray filteredArrayUsingPredicate:predicate]);
+1 Nunca he pensado en poner el selector directamente en el predicado. ¡Ordenado! –
No se menciona en la Guía de programación de predicados (lo que significa que hacer esto en una cadena de formato no está documentada técnicamente), pero la función de selector personalizado está respaldada por la referencia: http://developer.apple.com/mac/library/ documentation/Cocoa/Reference/Foundation/Classes/NSComparisonPredicate_Class/Reference/NSComparisonPredicate.html # // apple_ref/occ/clm/NSComparisonPredicate/predicateWithLeftExpression: rightExpression: customSelector: Muy bueno. –
Sí, originalmente lo escribí por el camino largo, pero lo intenté en el formato de cadena y me sorprendió ver que funcionaba. –
A partir de IOS 4 y Mac OS 10.6, se puede utilizar +[NSPredicate predicateWithBlock:]
también. Por ejemplo,
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [object isKindOfClass:[NSString class]];
}];
Esto le permite expresar sus predicados puramente en Objective-C en lugar de la sintaxis requerida por el predicado predicateWithFormat:
.
este se merece más votos –
¿Por qué se ponen objetos tan diferentes en la misma matriz en primer lugar? –
Una razón es si tiene una matriz de clases abstractas. Puede tener todas las clases de Persona, pero desea filtrar a Doctores o Abogados. – rob5408