首页 > 解决方案 > 如何像目录树一样向 NSOutlineView 上的节点添加更多节点?

问题描述

每次节点可扩展时,我都想在 NSOutlineView 上获取并显示用户主目录。

到目前为止,我只能获得第一级并将其扩展到第二级。

我想它必须附加到索引或类似的东西上。

我可以获得级别 1 和级别 2。当我单击级别 2 时,例如 Documents,有一个目录 yourDirectoryName,其中包含更多目录。我想显示箭头并能够在树上继续前进

第一张照片是我的应用程序。第二张图片是filezilla的一个例子

我的应用程序目前显示它

它必须是的一个例子

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

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

class ViewController: NSViewController {
var directories = [Directories]()
@IBOutlet weak var outlineView: NSOutlineView!

override func viewDidLoad() {
    super.viewDidLoad()
    getDir(path: "")
    outlineView.dataSource = self
    outlineView.delegate = self
}



func getDir(path: String) {
     let fm = FileManager.default.homeDirectoryForCurrentUser

    do {
        let items = contentsOf(folder: fm)
        for item in items {
            let sub = getSubDir(path: item.lastPathComponent)
            let re = Directories(name: item.lastPathComponent, subDirectories: sub)
            directories.append(re)
        }
    }
}

func contentsOf(folder: URL) -> [URL] {
    let fileManager = FileManager.default
    do {
        let contents = try fileManager.contentsOfDirectory(atPath: folder.path)

        let urls = contents.map { return folder.appendingPathComponent($0) }
        return urls
    } catch {
        return []
    }
}

func getSubDir(path: String) -> [String]{
    var sub = [String]()
    let fm = FileManager.default
    let filePath = NSString(string: path).expandingTildeInPath
    do {
        let items = try fm.contentsOfDirectory(atPath: filePath)
        for item in items {
            sub.append(item)
        }
    } catch {
        // failed to read directory
    }
    return sub
}

override var representedObject: Any? {
    didSet {
        // Update the view, if already loaded.
    }
}
}



extension ViewController: NSOutlineViewDataSource {
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
    if let directories = item as? Directories {
        return directories.subDirectories[index]
    }
    return directories[index]
}

func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
    if let directories = item as? Directories {
        return directories.subDirectories.count > 0
    }
    return false
}

func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
    if let directories = item as? Directories {
        return directories.subDirectories.count
    }
    return directories.count
}
}

extension ViewController: NSOutlineViewDelegate {
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
    var text = ""
    if let directories = item as? Directories {
        text = directories.name
    }
    else {
        text = item as! String
    }

    let tableCell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "cell"), owner: self) as! NSTableCellView
    tableCell.textField!.stringValue = text
    return tableCell
}
}

标签: swiftmacosnsoutlineview

解决方案


将级别 2 扩展到 3 与将级别 1 扩展到 2 相同。子目录是一个目录,并且有自己的子目录。的subDirectories属性Directories应该是一个数组Directories。的directories属性ViewController指向目录树,可以是Directories.

例子:

class ViewController: NSViewController {

    // the rootItem is invisible
    var rootItem = DirectoryItem(url: FileManager.default.homeDirectoryForCurrentUser)

}


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 outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
        let directoryItem = item as? DirectoryItem ?? rootItem
        let tableCell = outlineView.makeView(withIdentifier: (tableColumn?.identifier)!, owner: self) as! NSTableCellView
        tableCell.textField!.stringValue = directoryItem.name
        return tableCell
    }

}


class DirectoryItem {

    var name: String
    var url: 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])
            return urls.map { DirectoryItem(url: $0) }
        } catch let error as NSError {
            return []
        }
    }()

    init(url: URL) {
        self.url = url
        self.name = url.lastPathComponent
    }

}

免责声明:我已经习惯了 Objective-C,但我正在努力使用 Swift。


推荐阅读