在NSTableView中重新加载数据,但保持当前选择

时间:2011-06-06 05:55:49

标签: objective-c cocoa macos nstableview fsevents

我有NSTableView显示目录的内容。我注意FSEvents,每次收到一个事件我都会重新加载我的表视图。 不幸的是,当前的选择随后消失了。有没有办法避免这种情况?

5 个答案:

答案 0 :(得分:10)

好吧,你可以在调用reloadData之前保存选择并在之后恢复它。

NSInteger row = [self.tableView selectedRow];
[self.tableView reloadData];
[self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];

在某些情况下,这对我有用。但是如果在所选行之前插入一些项目,则应该通过向其添加添加项目的数量来调整行变量。

答案 1 :(得分:7)

Swift 4.2

创建扩展并添加一个保留选择的方法。

extension NSTableView {

    func reloadDataKeepingSelection() {
        let selectedRowIndexes = self.selectedRowIndexes
        self.reloadData()
        self.selectRowIndexes(selectedRowIndexes, byExtendingSelection: true)
    }
}

如果您使用传统的填充表视图的方式(而不是NSArrayController),请执行此操作。

答案 2 :(得分:5)

这取决于您如何填充NSTableView。

如果您将表视图绑定到NSArrayController,而NSArrayController又包含表视图正在显示的项,则NSArrayController可以选择保留选择。您可以在Interface Builder中选择(或不选择)它作为NSArrayController上的属性。或者您可以在代码中使用setPreservesSelection方法。

但是,如果您在每次获得FSEvent时完全替换NSArrayController管理的项目数组,那么保留选择可能无法正常工作。不幸的是,关于NSArrayController的这个属性的Apple文档在何时可以并且不能保留选择方面有点模糊。

如果您没有使用NSArrayController,但可能使用dataSource来填充表视图,那么我认为您必须自己管理选择。

答案 3 :(得分:5)

在使用数据源的情况下,reloadData()上的头文件中的Apple文档就是

  

不维护选定的行。

要四处走动,您可以使用reloadDataForRowIndexes(rowIndexes: NSIndexSet, columnIndexes: NSIndexSet)。如同一个头文件中所述

  

对于可见的单元格,将调用适当的dataSource和delegate方法,并重新绘制单元格。

因此将重新加载数据,并保留选择。

答案 4 :(得分:4)

@ silvansky答案的变种。

这个没有必要跟踪插入/删除的项目数。它保持多种选择。

这个想法是...... 1.从当前选择中创建一个选定对象/节点的数组 2.使用reloadData刷新表格 3.对于在步骤1中获得的每个对象,找到/记录它的新索引
4.告诉表视图/大纲视图选择更新的索引集

- (void)refresh {
    // initialize some variables
    NSIndexSet *selectedIndexes = [self.outlineView selectedRowIndexes];
    NSMutableArray *selectedNodes = [NSMutableArray array];
    NSMutableIndexSet *updatedSelectedIndex = [NSMutableIndexSet indexSet];

    // 1. enumerate all selected indexes and record the nodes/objects
    [selectedIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
        [selectedNodes addObject:[self.outlineView itemAtRow:idx]];
    }];

    // 2. refresh the table which may add new objects/nodes
    [self.outlineView reloadData];

    // 3. for each node in step 1, find the new indexes
    for (id selectedNode in selectedNodes) {
        [updatedSelectedIndex addIndex:[self.outlineView rowForItem:selectedNode]];
    }

    // 4. tell the outline view to select the updated index set
    [self.outlineView selectRowIndexes:updatedSelectedIndex byExtendingSelection:NO];
}