Sil*_* St 2 macos nsoutlineview swift
我使用 NSOutlineView 自动保存展开状态。如果我在数据源更新时手动重新加载数据,则func outlineView(_ outlineView: NSOutlineView, itemForPersistentObject object: Any) -> Any?不再调用数据源方法,并且每个单元格都会崩溃。知道为什么会发生这种情况吗?
尝试使用 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
}
Run Code Online (Sandbox Code Playgroud)
这是重新加载数据:
viewModel.dataSource.subscribe(onNext: { [weak self] _ in
self?.outlineView.reloadData()
}).disposed(by: disposeBag)
Run Code Online (Sandbox Code Playgroud)
恕我直言,自动保存是一种不成熟的功能,它无法按预期工作。换句话说,它的实现方式是在您的应用程序启动时(仅一次)恢复状态,然后您就可以自己了。
\n利用outlineViewItemDidExpand(_:)&实现您自己的一个outlineViewItemDidCollapse(_:)(特别是当我们重新加载时,...)。
如果您不想实现自定义自动保存,可以使用一些技巧。但我不会依赖他们。
\nNSOutlineView继承自NSTableView并且autosaveName属性文档说:
\n\n如果将此属性的值更改为新名称,表会读取所有已保存的信息,并设置此表 view\xe2\x80\x99s 列的顺序和宽度以进行匹配。将名称设置为
\nnil将从用户默认值中删除任何先前存储的状态。
这里不准确的是 - 将其设置为nil不会删除以前存储的扩展项目状态NSOutlineView。我们可以使用它来强制重新NSOutlineView加载扩展项目状态:
class ViewController: NSViewController, NSOutlineViewDelegate, NSOutlineViewDataSource {\n @IBOutlet var outlineView: NSOutlineView!\n // It\'s for testing, to demonstrate the persistent state reloading\n private var doNotLoad = true\n\n override func viewDidAppear() {\n super.viewDidAppear()\n \n DispatchQueue.main.asyncAfter(deadline: .now() + 3) {\n self.doNotLoad = false\n \n let autosaveName = self.outlineView.autosaveName\n self.outlineView.autosaveName = nil \n self.outlineView.reloadData()\n self.outlineView.autosaveName = autosaveName\n }\n }\n\n func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {\n if (doNotLoad) {\n return 0\n }\n return item == nil ? data.count : (item as! Node).children.count\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n如果您想遵守文档,请不要使用nil和设置一些假名称。但我希望一旦 bug 被修复,如果我们更改autosaveName或将其设置为 ,则持久状态将被删除nil。
假设您有以下Node课程:
class Node {\n let id: Int\n let children: [Node]\n // ...\n}\nRun Code Online (Sandbox Code Playgroud)\n并且您的数据源实现:
\nfunc outlineView(_ outlineView: NSOutlineView, persistentObjectForItem item: Any?) -> Any? {\n (item as! Node).id\n}\n\nfunc outlineView(_ outlineView: NSOutlineView, itemForPersistentObject object: Any) -> Any? {\n guard let id = object as? Int else { return nil }\n return data.firstNode { $0.id == id }\n}\nRun Code Online (Sandbox Code Playgroud)\n这firstNode与这个问题无关,但这里是实现(因为它在代码中提到):
extension Array where Self.Element == Node {\n // Search for a node (recursively) until a matching element is found\n func firstNode(where predicate: (Element) throws -> Bool) rethrows -> Element? {\n for element in self {\n if try predicate(element) {\n return element\n }\n if let matched = try element.children.firstNode(where: predicate) {\n return matched\n }\n }\n return nil\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n然后你可以reloadData自己展开所有项目:
outlineView.reloadData()\nif outlineView.autosaveExpandedItems,\n let autosaveName = outlineView.autosaveName,\n let persistentObjects = UserDefaults.standard.array(forKey: "NSOutlineView Items \\(autosaveName)"),\n let itemIds = persistentObjects as? [Int] {\n \n itemIds.forEach {\n let item = outlineView.dataSource?.outlineView?(self.outlineView, itemForPersistentObject: $0)\n self.outlineView.expandItem(item)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
576 次 |
| 最近记录: |