Swift   发布时间:2022-04-30  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了swift – 将NSTreeController与NSOutlineView一起使用大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_772_0@
@H_772_0@
我正在尝试(不成功)构建一个TreeController控制的NSOutlineView.我已经阅读了很多教程,但他们都在开始之前预先加载了数据,这对我来说不起作用.

我有一个简单的设备类:

import Cocoa
class Device: NSObject {
    let name : String
    var children = [service]()
    var serviceNo = 1
    var count = 0

    init(name: String){
        self.name = name
    }

    func addservice(servicename: String){
        let serv = "\(serviceName) # \(serviceNo)"
        children.append(service(name: serv))
        serviceNo += 1
        count = children.count
    }

    func isLeaf() -> Bool {
        return children.count < 1
    }
}

我还有一个更简单的“服务”课程:

import Cocoa
class service: NSObject {

    let name: String

    init(name: String){
        self.name = name
    }
}

最后,我有ViewController:

class ViewController: NSViewController {

    var stepper = 0

    dynamic var devices = [Device]()
    override func viewDidLoad() {
        super.viewDidLoad()
    }

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

    @IBACtion func addDeviceAction(_ sender: Any) {
        let str = "New Device #\(stepper)"
        devices.append(Device(name: str))
        stepper += 1
        print("Added Device: \(devices[devices.count-1].Name)")    
    }

    @IBACtion func addservice(_ sender: Any) {
        for i in 0..<devices.count {
            devices[i].addservice(servicename: "New service")
       }
    }
}

显然我有2个按钮,一个添加“设备”,另一个为每个设备添加“服务”.

我无法实现的是NSOutlineView中显示的任何数据.我已经将TreeController的对象控制器属性设置为Mode:Class和Class:Device,并且没有设置我得到的Children,Count或Leaf属性(可预测):

如果我然后将Children属性设置为’children’则会非常糟糕:

要做的就是设置NSOutlineView来从NSTreeController获取输入,这样当一个新的’Device’被添加到devices []数组时,它会显示在Outline视图中.

如果有人能指出我正确的方向,我将非常感激.

非常感谢沃伦的非常有益的工作.我(大部分)都在工作.除了沃伦的建议之外,我还需要做一些事情:

swift – 将NSTreeController与NSOutlineView一起使用


设置树控制器的数据存储

swift – 将NSTreeController与NSOutlineView一起使用


将OutlineView绑定到TreeController

swift – 将NSTreeController与NSOutlineView一起使用


将列绑定到TreeController

swift – 将NSTreeController与NSOutlineView一起使用


将TableView单元格绑定到表格单元格视图(是的,真的)

完成所有这些后,我不得不稍微使用实际的数据存储区:

var name = "Bluetooth Devices Root"
var deviceStore = [Device]()
@IBOutlet var treeController: NSTreeController!
@IBOutlet weak var outlineView: NSOutlineView!


override func viewDidLoad() {
    super.viewDidLoad()
    deviceStore.append(Device(name: "Bluetooth Devices"))
    self.treeController.content = self
}

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

@IBACtion func addDeviceAction(_ sender: Any) {
    if(deviceStore[0].name == "Bluetooth Devices"){
        deviceStore.remove(at: 0)
    }

事实证明,Root在开始时不能没有孩子,至少就我所知.一旦我添加一个孩子,我就可以删除占位符值,并且树似乎可以正常工作(大部分).另一件事是我必须重新加载数据并在数据发生变化时重新显示大纲:

outlineView.reloadData()
 outlineView.setNeedsDisplay()

没有它,没有.我仍然没有正确更新数据(请参阅Warren的回答下面的评论),但我差不多了.

解决方法

为了说明这一点,NSTreeController管理一个对象树,所有这些对象都需要回答以下三个问题/请求.

>你是一片叶子,即你没有孩子吗? = leafKeyPath
>如果你不是叶子,你有多少个孩子? = countKeyPath
>把你的孩子给我! = childrenKeyPath

它很容易在IB或编程中设置它们.分别是一组相当标准的属性.

> isLeaf
> childCount
>孩子们

但它完全是任意的,可以是回答这些问题的任何属性集.

我通常会设置一个名为TreeNode的协议,并使我的所有对象都符合它.

@objc protocol TreeNode:class { 
    var isLeaf:Bool { get }
    var childCount:Int { get }
    var children:[TreeNode] { get } 
}

对于您的Device对象,您可以使用isLeaf和children回答2个问题,但不回答childCount问题.

您的设备的子项是服务对象,它们不会回答这一点,这也是您获得例外的原因之一.

因此,要修复代码,可能的解决方案是……

服务对象

class service: NSObject,TreeNode {

    let name: String
    init(name: String){
        self.name = name
    }

    var isLeaf:Bool {
        return true
    }
    var childCount:Int {
        return 0
    }
    var children:[TreeNode] {
        return []
    }
}

Device对象

class Device: NSObject,TreeNode {
    let name : String
    var serviceStore = [service]()

    init(name: String){
        self.name = name
    }

    var isLeaf:Bool {
        return serviceStore.isEmpty
    }
    var childCount:Int {
        return serviceStore.count
    }
    var children:[TreeNode] {
        return serviceStore
    }

}

从MVC的角度来看,这是一个可怕的事情,但这个答案很方便.根对象.

class ViewController: NSViewController,TreeNode {

    var deviceStore = [Device]()
    var name = "Henry" //whatever you want to name your root

    var isLeaf:Bool {
        return deviceStore.isEmpty
    }
    var childCount:Int {
        return deviceStore.count
    }
    var children:[TreeNode] {
        return deviceStore
    }

}

所以你需要做的就是设置treeController的内容.让我们假设您在ViewController中有一个IBOutlet.

class ViewController: NSViewController,TreeNode {

    @IBOutlet var treeController:NSTreeController!
    @IBOutlet var outlineView:NSOutlineView!


    override func viewDidLoad() {
        super.viewDidLoad()
        treeController.content = self
    }

现在,每次附加设备或添加服务时,只需在outlineView上调用reloadItem(您还需要一个插座)

@IBACtion func addDeviceAction(_ sender: Any) {
        let str = "New Device #\(stepper)"
        devices.append(Device(name: str))
        stepper += 1
        print("Added Device: \(devices[devices.count-1].Name)")
        outlineView.reloadItem(self,reloadChildren: truE)    
    }

这是基础,应该让你开始,但NSOutlineView&的文档. NSTreeController有更多信息.

编辑

除了上面的内容之外,您还需要将大纲视图绑定到树控制器.

首先确保您的大纲视图处于查看模式.

swift – 将NSTreeController与NSOutlineView一起使用

接下来将表列绑定到树控制器上的arrangeObjects.

swift – 将NSTreeController与NSOutlineView一起使用

最后将文本单元格绑定到相关的键路径.在你的情况下它的名字. objectValue是对单元格中对象的引用.

swift – 将NSTreeController与NSOutlineView一起使用

@H_772_0@

大佬总结

以上是大佬教程为你收集整理的swift – 将NSTreeController与NSOutlineView一起使用全部内容,希望文章能够帮你解决swift – 将NSTreeController与NSOutlineView一起使用所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:nsoutlineviewswift一起使用
猜你在找的Swift相关文章
其他相关热搜词更多
phpJavaPython程序员load如何string使用参数jquery开发安装listlinuxiosandroid工具javascriptcap