替换项目时 NSOutlineView reloadItem/reloadData 不工作

NSOutlineView reloadItem/reloadData not working when replacing an item

我有一个 view-based NSOutlineViewdataSource/delegate 模型而不是绑定到树控制器(我想控制 insert/update 动画)。

我正在替换我的模型中的一个项目,并且想在大纲视图中更新该特定行而不必调用 reloadData()

我无法让它工作。要么项目根本不更新,要么项目的展开状态不更新。根据 this,似乎在 NSOutlineView 内部进行了一些缓存,但即使有这些建议,我也无法让它工作。

我有:

(1) 大纲视图表示文件夹结构

(2) 首先,有一个文件:

(3) 然后文件被文件夹项替换:

 // Model update
 let oldFileItem = rootItem.children.first!
 rootItem.children.remove(at: 0)
 rootItem.children.append(Item(title: "Folder", children:[], isExpandable:true))

预期结果:

实际结果(reloadItem):

outlineView.reloadItem(oldFileItem) // I kept a reference

图标和标题已重新加载,但请注意缺少展开三角形。

我可以理解 reloadItem() 在这种情况下可能不起作用,因为旧项目不再是数据模型的一部分。奇怪的是,项目的标题和图标更新了,但展开状态没有。

实际结果 (reloadData(forRowIndexes:columnIndexes:):

outlineView.reloadData(forRowIndexes: IndexSet(integer:0), columnIndexes: IndexSet(integer:0))

没有任何影响。这是我期望的工作。

实际结果(remove/insert):

outlineView.removeItems(at: IndexSet(integer:0), inParent: rootItem, withAnimation: [])
outlineView.insertItems(at: IndexSet(integer:0), inParent: rootItem, withAnimation: [])

没有任何影响。

文档说 removeItems(): "The method does nothing if parent is not expanded." 并且 isExpanded 确实 return false 用于根节点,尽管它的 children 是可见的。对于根节点的直接 children 项,这是特殊行为吗?我在这里错过了什么?

供参考,我的数据模型:

class Item:NSObject {
    var title:String
    var children:[Item]
    var isExpandable:Bool

    init(title:String, children:[Item], isExpandable:Bool) {
        self.title = title
        self.children = children
        self.isExpandable = isExpandable
    }
}

供参考:

原来是我使用 API 的问题。 NSOutlineView.removeItems/insertItems 期望根项目的 inParent 参数为 nil。我正在提交实际的 根项目 。使用 nil 而不是根项解决了问题。