Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 为什么使用autosaveExpandedItems true的基于视图的NSOutlineView会在重新加载数据时忽略扩展?_Swift_Macos_Nsoutlineview - Fatal编程技术网

Swift 为什么使用autosaveExpandedItems true的基于视图的NSOutlineView会在重新加载数据时忽略扩展?

Swift 为什么使用autosaveExpandedItems true的基于视图的NSOutlineView会在重新加载数据时忽略扩展?,swift,macos,nsoutlineview,Swift,Macos,Nsoutlineview,我使用自动保存扩展状态的NSOutlineView。如果我在数据源更新时手动重新加载数据,则不再调用func-outlineView(\uoutlineview:NSOutlineView,itemforpersistenobject-object:Any)->Any?dataSource方法,并且每个单元格都会折叠。知道为什么会这样吗 尝试使用nil send作为参数重新加载项,但仍然无效 我使用它来持久化展开的行: func outlineView(_ outlineView: NSOutl

我使用自动保存扩展状态的NSOutlineView。如果我在数据源更新时手动重新加载数据,则不再调用
func-outlineView(\uoutlineview:NSOutlineView,itemforpersistenobject-object:Any)->Any?
dataSource方法,并且每个单元格都会折叠。知道为什么会这样吗

尝试使用nil send作为参数重新加载项,但仍然无效

我使用它来持久化展开的行:

func outlineView(_ outlineView: NSOutlineView, persistentObjectForItem item: Any?) -> Any? {
    return NSKeyedArchiver.archivedData(withRootObject: item)
}

func outlineView(_ outlineView: NSOutlineView, itemForPersistentObject object: Any) -> Any? {
    guard let data = object as? Data,
        let item = NSKeyedUnarchiver.unarchiveObject(with: data) as? Category else { return nil }
    let foundItem = recursiveSearch(for: item, in: viewModel.dataSource.value)
    return foundItem
}
这将重新加载数据:

  viewModel.dataSource.subscribe(onNext: { [weak self] _ in
            self?.outlineView.reloadData()
  }).disposed(by: disposeBag)

IMHO自动保存是一种半生不熟的功能,它不能像预期的那样工作。换句话说,它的实现方式是在应用程序启动时(仅启动一次)恢复状态,然后您就可以独立运行了

利用&(特别是当我们重新加载时,…)实现您自己的一个

如果不想实现自定义自动保存,可以使用两个技巧。但我不相信他们

第一个技巧-告诉NSOutlineView重新加载持久状态
NSOutlineView
继承自
NSTableView
,属性文档说明:

如果将此属性的值更改为新名称,则表将读入所有保存的信息,并将此表视图的列的顺序和宽度设置为匹配。将名称设置为
nil
将从用户默认值中删除以前存储的任何状态

此处不准确的地方-将其设置为
nil
不会删除先前存储的
NSOutlineView
的扩展项状态。我们可以使用它强制
NSOutlineView
重新加载扩展项状态:

class ViewController:NSViewController、NSOutlineViewDeleteGate、NSOutlineViewData源{
@IBVar outlineView:NSOutlineView!
//它用于测试,以演示持久状态重新加载
私有变量doNotLoad=true
覆盖函数ViewDidDisplay(){
super.viewdideappear()
DispatchQueue.main.asyncAfter(截止日期:.now()+3){
self.doNotLoad=false
让autosaveName=self.outlineView.autosaveName
self.outlineView.autosaveName=nil
self.outlineView.reloadData()
self.outlineView.autosaveName=autosaveName
}
}
func outlineView(outlineView:NSOutlineView,numberOfChildrenOfItem:Any?)->Int{
如果(不加载){
返回0
}
return item==nil?data.count:(item as!Node).children.count
}
}
如果您希望遵守文档,请不要使用
nil
并设置一些假名称。但是我希望,一旦bug被修复,如果我们更改
autosaveName
或者将其设置为
nil
,持久状态将被删除

第二个技巧-加载并扩展自己 假设您有以下
节点
类:

类节点{
让id:Int
让子节点:[节点]
// ...
}
并且您的数据源实现:

func-outlineView(outlineView:NSOutlineView,PersistentObject-ForItem-item:Any?)->Any?{
(项目名称为!节点).id
}
func outlineView(outlineView:NSOutlineView,itemForPersistentObject对象:任意)->任意?{
guard let id=对象为?Int else{return nil}
返回data.firstNode{$0.id==id}
}
firstNode
与这个问题无关,但这里是实现(因为代码中提到了它):

扩展数组,其中Self.Element==节点{ //搜索节点(递归),直到找到匹配的元素 func firstNode(其中谓词:(元素)抛出->布尔)再抛出->元素{ 自我元素{ if-try谓词(元素){ 返回元素 } 如果let matched=try element.children.firstNode(其中:谓词){ 回报匹配 } } 归零 } } 然后您可以自己
重新加载数据
&展开所有项目:

outlineView.reloadData()
如果outlineView.autosaveExpandedItems,
让autosaveName=outlineView.autosaveName,
让persistentObjects=UserDefaults.standard.array(forKey:“NSOutlineView Items\(autosaveName)”,
让itemIds=persistentObjects作为?[内部]{
itemIds.forEach{
让item=outlineView.dataSource?.outlineView?(self.outlineView,itemForPersistentObject:$0)
self.outlineView.expandItem(项目)
}
}

为什么
autosaveExpandedItems
:“大纲视图保存其展开项的状态,并在用户下次启动应用程序时恢复该状态”,来自:“大纲视图中的每个项目都必须是唯一的。为了使折叠状态在重新加载之间保持一致,项的指针必须保持不变,并且项必须保持等相等(:)相同。“数据是否已被替换或某个项目已更新?它正在保存状态,并在用户下次启动应用程序时恢复,但如果我确实需要更改某些内容并需要重新加载数据,该怎么办?”?整个持久化状态被丢弃,所有项都被折叠。。。在下一次发布时,将看到正确的扩展项目。不要重新加载所有项目,请更新更改。谢谢。另一个似乎有效的技巧是在重新加载数据后立即设置autosaveExpandedItems=false和autosaveExpandedItems=true。这使得outlineview向后扩展itemsYep,但请注意,这是危险的,因为文档中说持久存储将被清除。我们不知道这是否是代码或文档中的一个bug,也不知道它是否会在未来的版本中开始消除它。