2014-09-06 6 views
7

Data la seguente NSSortDescriptor per stringhe con Core Data:controllare il modo NSSortDescriptor ordina i valori nulli in Core Data

[NSSortDescriptor sortDescriptorWithKey:@"series" ascending:true selector:@selector(caseInsensitiveCompare:)] 

I risultati sono correttamente ordinati alfabeticamente ascendente. Tuttavia nei casi in cui è seriesnil, stringhe con nil valori sono posti in alto, con valori non-nil sia smistato da allora in poi, per esempio:

[nil, nil, nil, A, B, C, D...] 

Esiste un modo per controllare questo comportamento? I dati principali non consentono selettori personalizzati. Ecco una domanda simile al mio (non affrontare limitazione di Core Data, però):

NSSortDescriptor and nil values

+0

Per quanto ho scavato. Penso che non puoi. Dovrai crearne un altro senza valori nulli. – rptwsthi

risposta

8

Mentre non è possibile utilizzare un selettore personalizzato con Core Data, è possibile creare una sottoclasse NSSortDescriptor per modificare il comportamento predefinito. Qualcosa del genere dovrebbe funzionare:

#define NULL_OBJECT(a) ((a) == nil || [(a) isEqual:[NSNull null]]) 

@interface NilsLastSortDescriptor : NSSortDescriptor {} 
@end 

@implementation NilsLastSortDescriptor 

- (id)copyWithZone:(NSZone*)zone 
{ 
    return [[[self class] alloc] initWithKey:[self key] 
          ascending:[self ascending] selector:[self selector]]; 
} 

- (id)reversedSortDescriptor 
{ 
    return [[[self class] alloc] initWithKey:[self key] 
          ascending:![self ascending] selector:[self selector]]; 
} 

- (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2 
{ 
    if (NULL_OBJECT([object1 valueForKeyPath:[self key]]) && 
     NULL_OBJECT([object2 valueForKeyPath:[self key]])) 
     return NSOrderedSame; 

    if (NULL_OBJECT([object1 valueForKeyPath:[self key]])) 
     return NSOrderedDescending; 

    if (NULL_OBJECT([object2 valueForKeyPath:[self key]])) 
     return NSOrderedAscending; 

    return [super compareObject:object1 toObject:object2]; 
} 

@end 
+0

La macro 'NULL_OBJECT' valuta' a' due volte. Non cambia la semantica in questo caso perché non ci sono effetti collaterali dall'argomento, ma uno potrebbe facilmente dimenticarlo in futuro. Finisce per raddoppiare le chiamate a '-valueForKeyPath:' e '-key'. Meglio usare una funzione inline statica. Mentre ci sei, potrebbe anche fare quelle chiamate una sola volta in '-compareObject: toObject:'. La natura dei descrittori di ordinamento è che vengono chiamati frequentemente, quindi le prestazioni sono importanti. Infine, '[NSNull null]' è documentato come un singleton, quindi puoi semplicemente usare l'uguaglianza del puntatore per controllarlo. –

+0

Questo approccio non ha funzionato per me se utilizzato in un controller di risultati recuperato. Sospetto che in questo caso CoreData converta i descrittori di ordinamento in query SQL, senza mai chiamare compareObject: –

Problemi correlati