swift - 如何从一个孩子扩展到它的第一个父母?
问题描述
我正在尝试从根(父级的父级......)开始扩展所有子级,直到实际节点。如何在不单击每个节点的情况下做到这一点?
我正在使用它来显示目录内容,并且我想显示用户在关闭/打开应用程序之前的最后一条路径。
第一张照片显示了我想要的样子,第二张照片显示了目前显示的内容。
代码没有完成。有很多测试和调试。
我在这个问题中添加了所有相关代码。
到目前为止,我的应用程序读取目录,如果此目录中有任何 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()
}
}
解决方案
如果您保存了用户上次访问的 URL,则可以分三个步骤显示并选择它:
DirectoryItem
将 URL 转换为表示 URL 的路径组件的数组。要求大纲视图展开每个项目,从根节点的直接子项目开始。
要求大纲视图选择最后一项。
未经测试的代码:
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
}
推荐阅读
- laravel - 是否可以获得存储磁盘中的文件 - “本地”?
- reactjs - 放大 GraphQL 从 ID 以外的其他字段获取项目
- scala - 使用 scala API,如何将一个 HDFS 位置的所有文件复制到另一个 HDFS 位置
- rstudio - 如何增加 RStudio 编辑器的行高?
- flutter - 如何使用颤动的 onChange 事件修复光标移动?
- image-processing - 带有 HOG 和 Euclidian/SVM 的 Canny edge 用于文件夹中的多个图像
- firebase - 服务器端请求的firestore安全规则
- eclipse - 是否有相当于 VS Studio “Go to All”(CTRL + T)的 Eclipse
- ios - Phaser Audio 在 Android 和浏览器中工作,但 iOS 给出错误:缓存中缺少音频键“ཁ”
- html - VSCode - 您没有用于调试 HTML 错误的扩展