我正在尝试在大纲视图上展开并选择项目的子项,但是我唯一能做的就是选择根项目,然后仅展开该项目,而不是其子项。
我用目录填充了Outlineview。每当项目可扩展时,都会加载其子目录。
我得到了一些帮助(How to expand from a child to its very first parent?),可以选择并扩展根。
展开一个项目时,我保存位置。因此,下次打开该应用程序时,它将显示从根目录扩展到保存路径的所有项目。
例如,当我选择“桌面”时,关闭并打开该应用程序,它将显示已选择并展开的桌面。
如果我在桌面下选择Dial或mp,则可以保存路径,但是当打开时,它会回到根目录,并且没有选择或扩展任何内容。
最终结果将是选择了转盘或mp并展开。
expandItem函数具有一个参数expandChild,但是它会扩展所有内容。我只想扩展到保存的路径即可。
var rootItem = DirectoryItem(url: FileManager.default.homeDirectoryForCurrentUser)
override func viewDidLoad() {
super.viewDidLoad()
let defaults = UserDefaults.standard
let lastDirectory = defaults.url(forKey: "LastDirectory")
outlineView.dataSource = self
outlineView.delegate = self
tableView.delegate = self
tableView.dataSource = self
tableView.doubleAction = #selector(doubleClickOnResultRow)
self.progressIndicator.isHidden = true
self.tableView.reloadData()
self.outlineView.reloadData()
reveal(URL(string: lastDirectory!.lastPathComponent) ?? FileManager.default.homeDirectoryForCurrentUser)
}
func reveal(_ url: URL) {
let items = itemHierarchy(for: url)
for item in items {
outlineView.expandItem(item, expandChildren: false)
let row = outlineView.row(forItem: item)
if(row != -1) {
let set = IndexSet(integer: row)
outlineView.selectRowIndexes(set, byExtendingSelection: false)
}
}
}
private func itemHierarchy(for url: URL) -> [DirectoryItem] {
var items: [DirectoryItem] = []
var current: DirectoryItem = rootItem
for component in url.pathComponents {
guard let child = current.childItems.first(where: { $0.name == component }) else {
return items
}
items.append(child)
current = child
}
return items
}
extension ViewController: NSOutlineViewDataSource {
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
let directoryItem = item as? DirectoryItem ?? rootItem
return directoryItem.childItems.count
}
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
let directoryItem = item as? DirectoryItem ?? rootItem
return directoryItem.childItems[index]
}
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
let directoryItem = item as? DirectoryItem ?? rootItem
return directoryItem.isExpandable
}
}
extension ViewController: NSOutlineViewDelegate {
func outlineViewSelectionDidChange(_ notification: Notification) {
singleClick()
}
func outlineView(_ outlineView: NSOutlineView, shouldExpandItem item: Any) -> Bool {
let directoryItem = item as? DirectoryItem ?? rootItem
return (directoryItem.childItems.count != 0)
}
func outlineView(_ outlineView: NSOutlineView, shouldShowOutlineCellForItem item: Any) -> Bool {
let directoryItem = item as? DirectoryItem ?? rootItem
return (directoryItem.childItems.count != 0)
}
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
var text = ""
if let directories = item as? DirectoryItem {
if(directories.isdir) {
text = directories.name
let tableCell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "cell"), owner: self) as! NSTableCellView
tableCell.textField!.stringValue = text
return tableCell
}
}
return nil
}
}
class Directories {
var name: String
var subDirectories: [String]
init(name: String, subDirectories: [String]) {
self.name = name
self.subDirectories = subDirectories
}
}
class DirectoryItem: CustomDebugStringConvertible {
var name: String
var url: URL
var isdir: Bool
var prev: URL
lazy var isExpandable: Bool = {
do {
return try url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory ?? false
} catch let error as NSError {
return false
}
}()
lazy var childItems: [DirectoryItem] = {
do {
let urls = try FileManager.default.contentsOfDirectory(at: url,
includingPropertiesForKeys: [.isDirectoryKey],
options: [.skipsHiddenFiles])
var aa: [DirectoryItem]
var bb: [DirectoryItem]
bb = []
aa = urls.map { DirectoryItem(url: $0) }
for a in aa {
if(a.isdir) {
bb.append(a)
// print(a)
}
}
return bb
//return urls.map { DirectoryItem(url: $0) }
} catch let error as NSError {
return []
}
}()
init(url: URL) {
self.url = url
self.name = url.lastPathComponent
self.isdir = url.hasDirectoryPath
self.prev = url.deletingLastPathComponent()
}
public var debugDescription: String {
return """
- url: \(self.url)
- name: \(self.name)
- isdir: \(self.isdir)
- prev: \(self.prev)
"""
}
}