2014-09-06 6 views
7

otrzymuje następujące NSSortDescriptor na smyczki z danych Core:Kontrolowanie sposobu NSSortDescriptor sortuje wartości zerowej w danych Core

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

Wyniki są właściwie uporządkowane alfabetycznie rosnąco. Jednakże w przypadkach, gdy series jest nil, smyczki z nil wartości są umieszczone na górze, z wartościami non-zerowe są klasyfikowane potem, na przykład:

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

Czy istnieje jakiś sposób, aby kontrolować to zachowanie? Dane podstawowe nie pozwalają na niestandardowe selektory. Oto podobne pytanie do kopalni (nie zwracając ograniczenie danych Core jest jednak):

NSSortDescriptor and nil values

+0

O ile mam kopać. Myślę, że nie możesz. Musisz utworzyć inny bez zerowych wartości. – rptwsthi

Odpowiedz

8

Chociaż nie można użyć niestandardowego selektora z danych Core można podklasy NSSortDescriptor zmienić domyślne zachowanie. Coś takiego powinno zadziałać:

#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

Makro "NULL_OBJECT" dwukrotnie ocenia "a". Nie zmienia to semantyki w tym przypadku, ponieważ nie ma żadnych skutków ubocznych z argumentacji, ale można łatwo zapomnieć o tym w przyszłości. To w końcu podwaja wywołania do '-valueForKeyPath:' i '-key'. Lepiej używać statycznej funkcji inline. Podczas gdy jesteś w tym samym czasie, możesz wywoływać te połączenia tylko raz w '-compareObject: toObject:'. Natura deskryptorów sortowania polega na tym, że są one nazywane często, więc wydajność ma znaczenie. Wreszcie, "[NSNull null]" jest udokumentowane jako singleton, więc możesz po prostu użyć wskaźnika równości, aby to sprawdzić. –

+0

To podejście nie działa dla mnie, gdy jest używane w pobranym kontrolera wyników. Podejrzewam, że w tym przypadku CoreData konwertuje deskryptory sortowania na zapytania SQL, nigdy nie wywołując compareObject: –

Powiązane problemy