【问题标题】:Sorting nil-valued rows always to bottom in nstableview column在 nstableview 列中始终将 nil 值行排序到底部
【发布时间】:2010-06-29 22:37:24
【问题描述】:
我的应用程序中有一个NSTableview,其中包含几列。当我单击一个列标题以使其升序排序时,该列中具有零值的行将被排在顶部,然后是非零值行以升序排列。如果我重新单击同一列,首先将按降序显示非零值行,然后是零值行。
我想要做的是让 nil 值的行始终粘在底部。因此,首先应显示以升序或降序方式排序的非零值行,并且应将零值行保留在底部。如何以最好的方式做到这一点?
在这种情况下排序 - 据我了解 - 由 NSArrayController 的 arrangedObject: 完成。那么我应该继承NSArrayController 并在arrangedObjects: 方法中使用自定义排序算法,还是有更好的方法来获得上述结果?
【问题讨论】:
标签:
objective-c
cocoa
sorting
nstableview
【解决方案1】:
我通过创建 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
【解决方案2】:
非常感谢。正如我上面提到的,我总是希望将 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];
}