【问题标题】:In a NSTableView, how to sort the items based on their selection?在 NSTableView 中,如何根据项目的选择对项目进行排序?
【发布时间】:2019-05-20 14:12:21
【问题描述】:

我正在用 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];

我希望有人能指出我正确的方向,可能尝试使用选择索引而不是选定对象的数组。再次感谢。

【问题讨论】:

    标签: objective-c macos cocoa nstableview


    【解决方案1】:

    如何获取选中的对象并追加未选中的对象

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

    我没有测试这个。

    【讨论】:

    • 感谢 Willeke,您的解决方案速度大约是我的 3 倍。再次感谢。
    【解决方案2】:

    我找到了一种实际上运行速度非常快的方法,但它并不优雅,并且肯定打破了我认为的 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"];
    }];
    

    非常感谢您的关注。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多