2010-06-29 58 views
2

我的應用程序中有一個包含多列的NSTableview。當我單擊一個列標題以便按升序排序時,該列中具有nil值的行將按照升序順序排列,然後是非nil值行。如果我重新點擊同一列,首先非降值行按照降序顯示,然後是零值行。在nstableview列中將nil值行總是排在最下面

我想要做的是讓無值的行總是粘在底部。因此,首先應該呈現以升序或降序方式排序的非零值行,而無值行應該保持在最低值。這怎麼能做到最好的方式呢?

在這種情況下排序 - 據我瞭解 - 由NSArrayControllerarrangedObject:完成。那麼我應該繼承NSArrayController並在arrangedObjects:方法中使用自定義排序算法,還是有更好的方法來獲得上述結果?

回答

0

我在自己的應用程序中通過創建NSSortDescriptor的自定義子類實現了這一點,這最終是NSArrayController用來執行排序的。實現如下,它並不複雜,但請注意,它將空字符串與零字符串一起排序。不幸的是,在Interface Builder中指定一個排序描述符子類是不可能的(至少我知道),所以你必須手動創建一個,然後調用setSortDescriptorPrototype:在你的awakeFromNib方法的適當的NSTableColumn中。

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

@interface MySortDescriptor : NSSortDescriptor {} 
@end 

@implementation MySortDescriptor 

- (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]] autorelease]; 
} 

- (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2 
{ 
    if (NULL_OBJECT([object1 valueForKeyPath:[self key]]) || 
     [[object1 valueForKeyPath:[self key]] length] == 0) 
     return ([self ascending] ? NSOrderedDescending : NSOrderedAscending); 
    if (NULL_OBJECT([object2 valueForKeyPath:[self key]]) || 
     [[object2 valueForKeyPath:[self key]] length] == 0) 
     return ([self ascending] ? NSOrderedAscending : NSOrderedDescending); 
    return [super compareObject:object1 toObject:object2]; 
} 

@end 
0

非常感謝。正如我上面提到的,我總是希望按照下面的方式將無符號值排序到底部。

- (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]; 
}