如何像目录树一样向 NSOutlineView 上的节点添加更多节点?
How to add more nodes to nodes on a NSOutlineView like a directory tree?
我想在每次节点可扩展时获取并显示 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([=10=]) }
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
}
}
2级扩3级和1级扩2级一样,子目录就是目录,有自己的子目录。 Directories
的subDirectories
属性应该是Directories
的数组。 ViewController
的 directories
属性 指向目录树,可以是 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: [=10=]) }
} catch let error as NSError {
return []
}
}()
init(url: URL) {
self.url = url
self.name = url.lastPathComponent
}
}
免责声明:我已经习惯了 Objective-C 而我正在为 Swift 而苦苦挣扎。
我想在每次节点可扩展时获取并显示 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([=10=]) }
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
}
}
2级扩3级和1级扩2级一样,子目录就是目录,有自己的子目录。 Directories
的subDirectories
属性应该是Directories
的数组。 ViewController
的 directories
属性 指向目录树,可以是 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: [=10=]) }
} catch let error as NSError {
return []
}
}()
init(url: URL) {
self.url = url
self.name = url.lastPathComponent
}
}
免责声明:我已经习惯了 Objective-C 而我正在为 Swift 而苦苦挣扎。