【问题标题】:reloadData in NSTableView but keep current selectionNSTableView 中的 reloadData 但保留当前选择
【发布时间】:2011-06-06 05:55:49
【问题描述】:

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

【问题讨论】:

    标签: objective-c cocoa macos nstableview fsevents


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      斯威夫特 4.2

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

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

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

      【讨论】:

      • 小注,这里会选择第一个&上一个选中的item,如果只想要前一个选中的item,设置“byExtendingSelection”为false
      【解决方案3】:

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

      不维护所选行。

      要绕过,您可以使用reloadDataForRowIndexes(rowIndexes: NSIndexSet, columnIndexes: NSIndexSet)。在同一个头文件中提到

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

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

      【讨论】:

        【解决方案4】:

        这取决于您如何填充 NSTableView。

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

        但是,如果您在每次获取 FSEvents 时完全替换 NSArrayController 管理的项目数组,那么可能无法保存选择。不幸的是,关于 NSArrayController 的此属性的 Apple 文档对于何时可以保留选择以及何时不能保留选择有点模糊。

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

        【讨论】:

        • 感谢您的解释。我真的在考虑使用 NSArrayController
        • 我发现 setPreservesSelection 非常不可靠。有时有效,有时无效。
        【解决方案5】:

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

        【讨论】:

        • 布拉德,你试过这个吗? reloadData 是延迟加载的,因此您在调用后不会有更新的数据。要在更改行顺序的拖动/移动操作后测试此代码。我认为它不会产生预期的结果。
        • @SteveSheldon 我确实记得这个工作,但不幸的是这个项目不再运行,所以我不能再测试了。
        • @SteveSheldon,我认为这行得通;我使用了类似的技术;如果我记得,Apple 的文档甚至提到了这一点。您指的是哪些更新数据?在哪个电话之后?
        猜你喜欢
        • 2015-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-20
        • 1970-01-01
        • 2011-11-05
        相关资源
        最近更新 更多