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

发布于 2024-11-14 03:21:13 字数 87 浏览 3 评论 0原文

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

I have anNSTableView showing the contents of a directory. I watch for FSEvents, and each time I get an event I reload my table view.
Unfortunately, the current selection then disappears. Is there a way to avoid that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

心安伴我暖 2024-11-21 03:21:13

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

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

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

Well, you can save selection before calling reloadData and restore it after that.

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

This worked for me in some cases. But if you insert some items BEFORE the selected row, you should andjust your row variable by adding count of added items to it.

梦里泪两行 2024-11-21 03:21:13

Swift 4.2

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

extension NSTableView {

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

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

Swift 4.2

Create an extension and add a method which preserves selection.

extension NSTableView {

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

Do this in case you use the traditional way of populating table views (not NSArrayController).

溺深海 2024-11-21 03:21:13

这取决于您如何填充 NSTableView。

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

但是,如果每次获取 FSEvent 时完全替换 NSArrayController 管理的项目数组,那么选择的保存可能无法工作。不幸的是,关于 NSArrayController 这个属性的 Apple 文档对于何时可以和不能保留选择有点含糊。

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

It depends on how you populate your NSTableView.

If you have the table view bound to an NSArrayController, which in turn contain the items that your table view is displaying, then the NSArrayController has an option to preserve the selection. You can select it (or not) from within Interface Builder as a property on the NSArrayController. Or you can use the setPreservesSelection method in code.

However, if you completely replace the array of items that the NSArrayController manages each time you get your FSEvents, then maybe the preservation of selection cannot work. Unfortunately the Apple docs on this property of NSArrayController are a bit vague as to when it can and cannot preserve the selection.

If you are not using an NSArrayController, but maybe using a dataSource to populate the table view, then I think you'll have to manage the selection yourself.

可爱暴击 2024-11-21 03:21:13

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

不保留所选行。

为了解决这个问题,您可以使用reloadDataForRowIndexes(rowIndexes: NSIndexSet, columnIndexes: NSIndexSet)。正如在同一个头文件中提到的

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

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

In the case of using Data Source, Apple Documentation in the header file on reloadData() is that

The selected rows are not maintained.

To get around, you can use reloadDataForRowIndexes(rowIndexes: NSIndexSet, columnIndexes: NSIndexSet). As mentioned in the same header file

For cells that are visible, appropriate dataSource and delegate methods will be called and the cells will be redrawn.

Thus the data will be reloaded, and the selection is kept as well.

热风软妹 2024-11-21 03:21:13

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

A variant on @silvansky's answer.

This one has no need to keep track of count of items inserted/deleted. And it maintains multiple selection.

The idea is to...
1. create an array of selected objects/nodes from the current selection.
2. refresh the table using reloadData
3. for each object obtained in step 1, find/record it's new index
4. tell the table view/outline view to select the updated index set

- (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];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文