swift - 如何从一个 child 扩展到它的第一个 parent ?

标签 swift macos nsoutlineview

我正在尝试展开从根节点(父节点的父节点……)开始的所有子节点,直到实际节点。如何在不点击每个节点的情况下做到这一点?

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

第一张图是我希望的样子,第二张图是现在显示的样子。

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

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

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

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

最佳答案

如果您保存了用户上次访问的 URL,那么您可以分三步显示和选择它:

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

  2. 要求大纲 View 展开这些项目中的每一个,从作为根节点的直接子节点的项目开始。

  3. 要求大纲 View 选择最后一项。

未经测试的代码:

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
}

关于swift - 如何从一个 child 扩展到它的第一个 parent ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56381341/

相关文章:

excel - 如何在Excel中使用VBA截断数字而不是四舍五入?

objective-c - "NSBinarySearchingFirstEqual = (1UL << 8)"在枚举定义中是什么意思?

c# - 同一个库之间的调用不明确?

objective-c - 如何设置顶级 NSOutlineView 项目的文本颜色

ios - 我正在尝试制作一款横向卷轴游戏,但我正在努力无限地生成地面

swift - 如何在文本标签上显示当前时间?

ios - Swift/SpriteKit 与自定义类的碰撞

swift - 我如何在 swift 2 中重写这段和平的代码

swift - 类似于 Finder 应用程序 NSOutlineView Cocoa Swift 的拖放

cocoa - 使用圆形矩形按钮作为带有计数器的徽章