Esiste un modo per costruire un predicato da filtrare in base al tipo di classe?È possibile filtrare un NSArray per classe?
Attualmente eseguo il loop della matrice e controllo la classe di ciascun oggetto. Forse c'è un modo più pulito?
Esiste un modo per costruire un predicato da filtrare in base al tipo di classe?È possibile filtrare un NSArray per classe?
Attualmente eseguo il loop della matrice e controllo la classe di ciascun oggetto. Forse c'è un modo più pulito?
Si potrebbe aggiungere una categoria per NSObject che aggiunge un metodo "cf_className", in questo modo:
@interface NSObject (CFAdditions)
- (NSString *) cf_className;
@end
@implementation NSObject (CFAdditions)
- (NSString *) cf_className {
return NSStringFromClass([self class]);
}
@end
Da lì, è possibile utilizzare i predicati come:
NSPredicate * p = [NSPredicate predicateWithFormat:@"cf_className = %@", aClass];
NSArray * filtered = [anArray filteredArrayUsingPredicate:p];
Se siete su il Mac, puoi semplicemente usare -[NSObject className]
invece di dover creare la categoria. L'iPhone non ha quel metodo, quindi la necessità di una categoria.
Puoi anche fare self.class.description –
@BrianKing punto eccellente –
È possibile confrontare direttamente le classi anche nel predicato.
Ma probabilmente non funzionerà come ci si aspetterebbe se si cerchi di filtrare per oggetti appartenenti a cluster di classi o se si dispone di sottoclassi.
Per esempio, NSDate
quando un'istanza è di solito un __NSCFDate
e NSString
può essere NSCFString
così come altre classi private specifiche.
Probabilmente è meglio semplicemente eseguire il loop del set e utilizzare -isKindOfClass:
come test.
SE si davvero desidera utilizzare NSPredicate
anche se si può fare questo. Ad esempio, questo filtra una matrice per tutti gli oggetti derivati da NSString
. Se si desidera un abbonamento di classe rigoroso, è possibile sostituire isKindOfClass:
con isMemberOfClass:
.
Qualsiasi selettore che implementa tutti gli oggetti nella raccolta, accetta un argomento e restituisce un BOOL
dovrebbe funzionare.
NSArray *mixedArray = {...};
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"self isKindOfClass: %@",
[NSString class]];
NSLog(@"%@", [mixedArray filteredArrayUsingPredicate:predicate]);
+1 Non ho mai pensato di mettere il selettore direttamente nel predicato. Neat! –
Non è menzionato nella Predicate Programming Guide (il che significa che fare questo in una stringa di formato è tecnicamente non documentato), ma la funzione di selezione personalizzata è supportata dal riferimento: http://developer.apple.com/mac/library/ documentazione/Cacao/Riferimento/Fondazione/Classi/NSComparisonPredicate_Class/Riferimento/NSComparisonPredicate.html # // apple_ref/occ/clm/NSComparisonPredicate/predicateWithLeftExpression: rightEspressione: customSelector: molto interessante. –
Sì, originariamente avevo scritto la lunga strada ma su un allodole l'ho provato nella stringa di formato e sono rimasto sorpreso nel vederlo funzionare. –
partire in iOS 4 e Mac OS 10.6, si può usare +[NSPredicate predicateWithBlock:]
pure. Per esempio:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [object isKindOfClass:[NSString class]];
}];
questo ti permette di esprimere i propri predicati puramente in Objective-C, piuttosto che la sintassi predicato richiesto dalla predicateWithFormat:
.
questo merita più voti –
Perché stai mettendo oggetti così diversi nello stesso array in primo luogo? –
Una ragione è se si dispone di una matrice di classi astratte. Puoi avere tutti i corsi Person, ma vuoi filtrare Medici o Avvocati. – rob5408