首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Xcode9 Swift4.2 4.2 NSOutlineView NSTreeController数据

Xcode9 Swift4.2 4.2 NSOutlineView NSTreeController数据
EN

Stack Overflow用户
提问于 2018-11-18 04:01:40
回答 1查看 118关注 0票数 0

我正在尝试在一个MacOS应用程序中创建一个大纲视图,该应用程序具有多个级别,这些级别是SQLite3中保存的一组数据的摘要。我有一个大纲视图与一个基于模型类的非常简单的NSMutuableDictionary的树控制器一起工作。

代码语言:javascript
复制
import Cocoa
class Summary: NSObject {
    @objc dynamic var name: String
    @objc dynamic var trades: Int
    @objc dynamic var avgPL: Double
    @objc dynamic var pandl: Double
    @objc dynamic var parent: String
    @objc dynamic var isLeaf: Bool
    @objc dynamic var childCount: Int
    @objc dynamic var children: [Summary] = []
    init(name: String, trades: Int, avgPL: Double, pandl: Double, parent: String, isLeaf: Bool,childCount: Int) {
        self.name = name
        self.trades = trades
        self.avgPL = avgPL
        self.pandl = pandl
        self.parent = parent
        self.isLeaf = isLeaf
        self.childCount = childCount
    }
    @objc func add(child: Summary) {
        children.append(child)
    }
}

我的简单示例数据是:

代码语言:javascript
复制
    let root: [String : Any] = ["name": "Overall","trades":5,"avgPL":200,"pandl":500,"parent":"","isLeaf": false,"childCount": 2 ]
    let dict: NSMutableDictionary = NSMutableDictionary(dictionary: root)
    let l2a = Summary(name: "L2a", trades: 3, avgPL: 100, pandl: 300, parent: "L1",isLeaf: true,childCount: 0)
    let l2b = Summary(name: "L2b", trades: 2, avgPL: 100, pandl: 200, parent: "L1",isLeaf: true,childCount: 0)
    dict.setObject([l2a,l2b], forKey: "children" as NSCopying)

我将字典传递给treeController:

代码语言:javascript
复制
treeController.addObject(dict)

这很好地给了我一个可折叠的轮廓:

但是我不知道如何给孩子添加更多的关卡或者孩子。我希望在大纲中最多有四个层次。我有了所有的SQL摘要,并且我尝试了许多填充数组的变体,并试图创建一个包含数据的字典,但都无济于事。我有孩子和childCount和isLeaf设置的所有东西,但树控制器不喜欢数组抱怨isLeaf不符合KVO。我在数组中的数据看起来像这样(不是所有数据,但足以看到我在做什么),主层和所有后续的子类都基于上面的Summary模型类。我能简单地把这个数组转换成字典吗?或者,我可以通过向model类添加键来使其符合KVO吗?如果有用的话,我将所有4个级别放在单独的数组中,用来构建结果数组:

我应该补充的是,我有一个定义为NSMutableArray的NSObject,它的内容绑定到treeController。我的treeController绑定到模型类中的每个变量,并且在顶层具有:

如果我将已构建的数组传递给treeController,则会得到以下错误:

代码语言:javascript
复制
Failed to set (contentViewController) user defined inspected property on (NSWindow): [<_TtGCs23_ContiguousArrayStorageC11outlinetest7Summary_ 0x604000445160> addObserver:forKeyPath:options:context:] is not supported. Key path: isLeaf
EN

回答 1

Stack Overflow用户

发布于 2018-11-25 18:55:44

在没有NSTreeController的情况下构建了我的NSOutlineView并使一切正常工作之后,我仍然希望回到这一点并实现treeController,以便利用它提供的排序机制。我确实发现,正如我上一条评论所说的那样,我在InterfaceBuilder中确实存在一些错误,导致它抱怨KVO遵从性。除了treeController上的Content Array绑定之外,我已经正确地连接了所有内容。在这里,我将它绑定到我的ViewController,并将我的数据数组reportSummary添加到模型键路径。

我也不再需要使用treeController.addObject(reportSummary)手动将我的数据数组添加到treeController。一旦这起作用了,我就可以实现排序了,一切都很好。我应该指出两件事。

TreeController上的

  1. 排序设置与绑定到TableView的ArrayController上的排序设置略有不同。使用表视图,在IB的身份检查器中指定哪些列是可排序的就足够了。但是在outlineView场景中,我还需要在IB中设置到treeController的绑定,并将Controler键从arrangedObjects更改为sortDescriptors
  2. 在测试我的树控大纲视图时,当我双击摘要行时遇到了一个问题。我在IB中的outlineView上实现了Double Action,以控制摘要部分的展开和折叠。请注意,我在这里的一个线程中读到过这样做,有人提到您需要维护多个数组和跟踪索引,因为一旦一行折叠或展开,就会更改所有后续行的行号。但我发现解决方案就是以相反的顺序遍历各行,然后从outlineView.numberOfRows-1开始沿树向上展开或折叠它们。这很有效,除了双击(点击)展开和折叠,我还添加了一个NSSlider,它跟踪到展开级别,并让我折叠所有最低级别,向树上移动,而不是单击每行上的所有小箭头。当我实现treeController时,这个问题就被破坏了。我收到一个错误

无法强制转换'NSKVONotifying_NSTreeControllerTreeNode‘类型的值

这行代码就是问题所在

代码语言:javascript
复制
let summary = reportOutline.item(atRow: x) as! Summary

我不得不把这个改成

代码语言:javascript
复制
let node = reportOutline.item(atRow: x) as! NSTreeNode
let summary = node.representedObject as! Summary

就是这样。现在工作得很好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53355050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档