如何从一个孩子扩展到其第一个父母?

时间:2019-05-30 15:37:11

标签: swift macos nsoutlineview

我正在尝试从根(父级的父级...)开始扩展所有子级,直到实际节点。不用单击每个节点怎么办?

我正在使用它来显示目录内容,并且想要显示用户在关闭/打开应用程序之前的最后路径。

第一张图片显示了我想要的样子,第二张图片显示了当前显示的内容。

代码未完成。有很多测试和调试。

我在此问题中添加了所有相关代码。

到目前为止,我的应用程序读取目录,并且如果此目录上有任何mp3文件,它将显示在表格视图中,但这不是我的问题的一部分,而只是背景。

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
}
}

@objc func singleClick()
{
    if let item = self.outlineView.item(atRow: self.outlineView.selectedRow)  {
        self.arrMp3File.removeAll()
        do {
            let xx = (item as! DirectoryItem).url
            let b = self.getSubDir(path: xx.path)
            self.saveDefaults(url: xx)
            DispatchQueue.global(qos: .background).async { [weak self] in
                DispatchQueue.main.async {
                    self?.progressIndicator.isHidden = false
                    self?.progressIndicator.startAnimation(self)
                }
                for bb in b {
                    self?.getTagsFromFile(file: xx.path+"/"+bb)
                }
                DispatchQueue.main.async {
                    self?.arrMp3File.sort(by: {
                        $0.file < $1.file
                    })
                    self?.tableView.reloadData()
                    self?.loadTagsFromButton.isEnabled = true
                    self?.progressIndicator.stopAnimation(self)
                    self?.progressIndicator.isHidden = true
                }
            }
        }
    }   

}

override func viewDidLoad() {
    super.viewDidLoad()
     let defaults = UserDefaults.standard

    let lastDirectory = defaults.url(forKey: "LastDirectory")
    print(lastDirectory ?? "")
   // rootItem = DirectoryItem(url: lastDirectory ?? FileManager.default.homeDirectoryForCurrentUser)
   // getDir(path: age)
    outlineView.dataSource = self
    outlineView.delegate = self

    tableView.delegate = self
    tableView.dataSource = self

    tableView.doubleAction = #selector(doubleClickOnResultRow)
  //  outlineView.action = #selector(singleClick)


  self.progressIndicator.isHidden = true
    self.tableView.reloadData()

}

class Directories {
var name: String
var subDirectories: [String]

init(name: String, subDirectories: [String]) {
    self.name = name
    self.subDirectories = subDirectories
}
}


class DirectoryItem {

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()

}

}

What I would like to show

What is shown at the moment

1 个答案:

答案 0 :(得分:0)

如果您保存了用户上次访问的URL,则可以通过三个步骤显示并选择它:

  1. 将URL转换为表示URL路径组成的DirectoryItem数组。

  2. 询问大纲视图以从根节点的直接子项开始扩展这些项。

  3. 询问大纲视图以选择最后一项。

未经测试的代码:

func reveal(_ url: URL) {
    // Step 1.
    let items = itemHierarchy(for: url)

    // Step 2.
    for item in items {
        outlineView.expandItem(item)
    }

    // Step 3.
    if
        let last = items.last,
        case let row = outlineView.row(forItem: last),
        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
}