在nstableview列中将nil-values行总是排序到底部

时间:2010-06-29 22:37:25

标签: objective-c cocoa sorting nstableview

我的应用程序中有一个包含多个列的NSTableview。当我单击一个列标题以使其按升序排序时,该列中具有nil值的行将按顶部排序,然后按升序排列非零值行。如果我在同一列上单击,则首先按降序显示非零值行,然后是零值行。

我想要做的是将零值行总是粘在底部。因此,首先应该呈现以递增或递减方式排序的非零值行,并且应将零值行保持在底部。如何才能以最佳方式完成?

在此上下文中进行排序 - 据我所知 - 由NSArrayController的{​​{1}}完成。那么我应该将arrangedObject:子类化并在NSArrayController方法中使用自定义排序算法,还是有更好的方法来获得上述结果?

2 个答案:

答案 0 :(得分:0)

我在自己的应用程序中通过创建NSSortDescriptor的自定义子类来实现它,这最终是NSArrayController用于执行其排序的。实现如下,它并不是非常复杂,但请注意它将空字符串与nil字符串一起排序到最后。遗憾的是,我无法(至少我知道)在Interface Builder中指定排序描述符子类,因此您必须在awakeFromNib方法中的相应NSTableColumn上手动创建一个并调用setSortDescriptorPrototype:

#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

答案 1 :(得分:0)

非常感谢。正如我上面提到的,我总是希望将nil-values排序到底部我使用compareObject的代码:以下面的方式。

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