在 NSTableView 中,如何根据选择对项目进行排序?
In a NSTableView, how to sort the items based on their selection?
我正在 Objective-C 中开发 macOS 应用程序。我想添加一个功能选项来对 NSTableView 进行排序以在其他项之前显示所选项目。我的代码是:
NSUInteger idx = [self.itemsTableView.selectedRowIndexes firstIndex];
NSMutableArray *selectedObjects = [NSMutableArray new];
while (idx != NSNotFound)
{
// do work with "idx"
// NSLog (@"The current index is %lu", (unsigned long)idx);
[selectedObjects addObject:self.items[idx]];
// get the next index in the set
idx = [self.itemsTableView.selectedRowIndexes indexGreaterThanIndex:idx];
}
self.items = [self.unFilteredItems sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
BOOL obj1Exists = [selectedObjects containsObject:obj1];
BOOL obj2Exists = [selectedObjects containsObject:obj2];
if (obj1Exists && !obj2Exists) {
return NSOrderedAscending;
}
if (obj1Exists && obj2Exists) {
return NSOrderedSame;
}
if (!obj1Exists && !obj2Exists) {
return NSOrderedSame;
}
if (!obj1Exists && obj2Exists) {
return NSOrderedDescending;
}
return NSOrderedSame;
}];
[self.itemsTableView reloadData];
不幸的是,在大约 70.000 个项目和 4500 个项目的选择上,比较器花费了太多时间。任何人都可以指出我这个问题的替代解决方案吗?感谢您的帮助。
编辑:
我现在已经尝试了另一种解决方案,它被证明更快但仍然不够快:
NSUInteger idx = [self.myMessagesTableView.selectedRowIndexes firstIndex];
NSMutableArray *selectedObjects = [NSMutableArray new];
while (idx != NSNotFound)
{
// do work with "idx"
// NSLog (@"The current index is %lu", (unsigned long)idx);
[selectedObjects addObject:self.myMessages[idx]];
// get the next index in the set
idx = [self.myMessagesTableView.selectedRowIndexes indexGreaterThanIndex:idx];
}
NSMutableArray *unselectedObjects = [NSMutableArray new];
[self.unFilteredItems enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (![selectedObjects containsObject:obj]) {
[unselectedObjects addObject:obj];
}
}];
self.items = selectedObjects;
self.items = [self.items arrayByAddingObjectsFromArray:unselectedObjects];
[self.itemsTableView reloadData];
我希望有人能给我指出正确的方向,可能是尝试使用选择索引而不是选定对象的数组。再次感谢。
我找到了一种实际运行速度非常快的方法,但它并不优雅,而且肯定会破坏我认为的 MVC 模式,但它目前有效,因此非常欢迎任何其他更好的解决方案。我现在正在使用此代码:
NSUInteger idx = [self.itemsTableView.selectedRowIndexes firstIndex];
NSMutableArray *selectedObjects = [NSMutableArray new];
while (idx != NSNotFound)
{
// do work with "idx"
// NSLog (@"The current index is %lu", (unsigned long)idx);
[self.items[idx] setValue:@YES forKey:@"isItemSelected"];
[selectedObjects addObject:self.items[idx]];
// get the next index in the set
idx = [self.itemsTableView.selectedRowIndexes indexGreaterThanIndex:idx];
}
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"isItemSelected" ascending:NO];
self.items = [self.unFilteredItems sortedArrayUsingDescriptors:@[descriptor]];
[self.itemsTableView reloadData];
NSMutableIndexSet *set = [[NSMutableIndexSet alloc] init];
NSUInteger a = 0;
for (a=0;a<[selectedObjects count];a++) {
[set addIndex:a];
}
[self.itemsTableView selectRowIndexes:set byExtendingSelection:NO];
[selectedObjects enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeObjectForKey:@"isItemSelected"];
}];
非常感谢您的关注。
如何获取选中的对象并附加未选中的对象
NSArray *selectedObjects = [self.items objectsAtIndexes:self.itemsTableView.selectedRowIndexes];
// invert selectedRowIndexes
NSMutableIndexSet *invertedSelection = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.items.count)];
[invertedSelection removeIndexes:self.itemsTableView.selectedRowIndexes];
NSArray *unselectedObjects = [self.items objectsAtIndexes:invertedSelection];
self.items = [selectedObjects arrayByAddingObjectsFromArray:unselectedObjects];
self.itemsTableView.selectedRowIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, selectedObjects.count)];
[self.itemsTableView reloadData];
或者删除所选对象并将它们插入顶部
NSMutableArray *mutableItems = [self.items mutableCopy];
NSArray *selectedObjects = [self.items objectsAtIndexes:self.itemsTableView.selectedRowIndexes];
[mutableItems removeObjectsAtIndexes:self.itemsTableView.selectedRowIndexes];
NSindexSet *selectedIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, selectedObjects.count)]
[mutableItems insertObjects:selectedObjects atIndexes:selectedIndexes];
self.items = [mutableItems copy];
self.itemsTableView.selectedRowIndexes = selectedIndexes;
[self.itemsTableView reloadData];
我没有测试这个。
我正在 Objective-C 中开发 macOS 应用程序。我想添加一个功能选项来对 NSTableView 进行排序以在其他项之前显示所选项目。我的代码是:
NSUInteger idx = [self.itemsTableView.selectedRowIndexes firstIndex];
NSMutableArray *selectedObjects = [NSMutableArray new];
while (idx != NSNotFound)
{
// do work with "idx"
// NSLog (@"The current index is %lu", (unsigned long)idx);
[selectedObjects addObject:self.items[idx]];
// get the next index in the set
idx = [self.itemsTableView.selectedRowIndexes indexGreaterThanIndex:idx];
}
self.items = [self.unFilteredItems sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
BOOL obj1Exists = [selectedObjects containsObject:obj1];
BOOL obj2Exists = [selectedObjects containsObject:obj2];
if (obj1Exists && !obj2Exists) {
return NSOrderedAscending;
}
if (obj1Exists && obj2Exists) {
return NSOrderedSame;
}
if (!obj1Exists && !obj2Exists) {
return NSOrderedSame;
}
if (!obj1Exists && obj2Exists) {
return NSOrderedDescending;
}
return NSOrderedSame;
}];
[self.itemsTableView reloadData];
不幸的是,在大约 70.000 个项目和 4500 个项目的选择上,比较器花费了太多时间。任何人都可以指出我这个问题的替代解决方案吗?感谢您的帮助。
编辑:
我现在已经尝试了另一种解决方案,它被证明更快但仍然不够快:
NSUInteger idx = [self.myMessagesTableView.selectedRowIndexes firstIndex];
NSMutableArray *selectedObjects = [NSMutableArray new];
while (idx != NSNotFound)
{
// do work with "idx"
// NSLog (@"The current index is %lu", (unsigned long)idx);
[selectedObjects addObject:self.myMessages[idx]];
// get the next index in the set
idx = [self.myMessagesTableView.selectedRowIndexes indexGreaterThanIndex:idx];
}
NSMutableArray *unselectedObjects = [NSMutableArray new];
[self.unFilteredItems enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (![selectedObjects containsObject:obj]) {
[unselectedObjects addObject:obj];
}
}];
self.items = selectedObjects;
self.items = [self.items arrayByAddingObjectsFromArray:unselectedObjects];
[self.itemsTableView reloadData];
我希望有人能给我指出正确的方向,可能是尝试使用选择索引而不是选定对象的数组。再次感谢。
我找到了一种实际运行速度非常快的方法,但它并不优雅,而且肯定会破坏我认为的 MVC 模式,但它目前有效,因此非常欢迎任何其他更好的解决方案。我现在正在使用此代码:
NSUInteger idx = [self.itemsTableView.selectedRowIndexes firstIndex];
NSMutableArray *selectedObjects = [NSMutableArray new];
while (idx != NSNotFound)
{
// do work with "idx"
// NSLog (@"The current index is %lu", (unsigned long)idx);
[self.items[idx] setValue:@YES forKey:@"isItemSelected"];
[selectedObjects addObject:self.items[idx]];
// get the next index in the set
idx = [self.itemsTableView.selectedRowIndexes indexGreaterThanIndex:idx];
}
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"isItemSelected" ascending:NO];
self.items = [self.unFilteredItems sortedArrayUsingDescriptors:@[descriptor]];
[self.itemsTableView reloadData];
NSMutableIndexSet *set = [[NSMutableIndexSet alloc] init];
NSUInteger a = 0;
for (a=0;a<[selectedObjects count];a++) {
[set addIndex:a];
}
[self.itemsTableView selectRowIndexes:set byExtendingSelection:NO];
[selectedObjects enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeObjectForKey:@"isItemSelected"];
}];
非常感谢您的关注。
如何获取选中的对象并附加未选中的对象
NSArray *selectedObjects = [self.items objectsAtIndexes:self.itemsTableView.selectedRowIndexes];
// invert selectedRowIndexes
NSMutableIndexSet *invertedSelection = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.items.count)];
[invertedSelection removeIndexes:self.itemsTableView.selectedRowIndexes];
NSArray *unselectedObjects = [self.items objectsAtIndexes:invertedSelection];
self.items = [selectedObjects arrayByAddingObjectsFromArray:unselectedObjects];
self.itemsTableView.selectedRowIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, selectedObjects.count)];
[self.itemsTableView reloadData];
或者删除所选对象并将它们插入顶部
NSMutableArray *mutableItems = [self.items mutableCopy];
NSArray *selectedObjects = [self.items objectsAtIndexes:self.itemsTableView.selectedRowIndexes];
[mutableItems removeObjectsAtIndexes:self.itemsTableView.selectedRowIndexes];
NSindexSet *selectedIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, selectedObjects.count)]
[mutableItems insertObjects:selectedObjects atIndexes:selectedIndexes];
self.items = [mutableItems copy];
self.itemsTableView.selectedRowIndexes = selectedIndexes;
[self.itemsTableView reloadData];
我没有测试这个。