macOS - Swift 4.0 容器视图不显示 NSView

macOS - Swift 4.0 Container View does not show NSView

我正在使用 Swift 4.0 编写我的第一个 macOS 应用程序并且 目前我正在为我的容器视图而苦苦挣扎。

I've this layout

Layout while running the app

问题是,当我单击其中一个 TableView 项目时,我的 Container View 没有加载其中带有 "THEMA 1" 标签的 NSView。 (所有 TableView 项目都应加载 "THEMA 1" 视图)

这是我的 ViewController 代码

import Cocoa

class ViewController: NSViewController {

    //VARS
    var tableViewArray = ["Thema 1", "Thema 2", "Thema 3", "Thema 4", "Thema 5"]
    var containerViewArray: [NSView]!
    var thema1View = Thema1()

    //IBOutlets
    @IBOutlet weak var tableView: NSTableView!
    @IBOutlet weak var container: NSView!

    override func viewDidLoad() {
        super.viewDidLoad()

        //setup TableView
        tableView.delegate = self
        tableView.dataSource = self
        tableView.action = #selector(onItemClicked)
    }

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

}

//Extensions
extension ViewController: NSTableViewDelegate, NSTableViewDataSource {

    //show what is clicked on tableView
    @objc private func onItemClicked() {
        if (tableView.clickedRow <= tableViewArray.count - 1) && (tableView.clickedRow >= 0)  {
            print("\(tableViewArray[tableView.clickedRow]), clicked")
            removeAllSubView()
            container.addSubview(thema1View, positioned: .above, relativeTo: container)
        }
        else {
            print("There is no content in this cell")
        }

    }

    //removes all SubViews from containerView
    func removeAllSubView() {
        for view in container.subviews{
            view.removeFromSuperview()
        }
    }

    //rows in tableViewArray
    func numberOfRows(in tableView: NSTableView) -> Int {
        return tableViewArray.count
    }

    //populate the tableView
    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
        return tableViewArray[row]
    }

}

Thema1 ViewController 代码

import Cocoa

class Thema1: NSView {

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        // Drawing code here.
    }

}

我认为问题隐藏在 onItemClicked() 方法中,但正如我所提到的,我对 macOS 和 Swift 4.0 很陌生。 因此,我发现了很多关于 iOS 的结果,但只有少数 macOS,但没有任何迹象表明我的情况。

感谢您抽出宝贵时间并向您致以最诚挚的问候, 丹尼

我找到了示例代码 SourceView,但它相当复杂并且在 Objective-C 中。这是我把相关部分翻译成Swift(我对Swift不是很熟悉)。

class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {

    var tableViewArray = ["Thema 1", "Thema 2", "Thema 3", "Thema 4", "Thema 5"]
    var detailViewController: NSViewController?

    @IBOutlet weak var container: NSView!

    @IBAction func tableViewClickAction(_ tableView: NSTableView) {
        if tableView.clickedRow >= 0  {
            print("\(tableViewArray[tableView.clickedRow]), clicked")

            // remove the detail view if there is one
            if let oldViewController = detailViewController {
                oldViewController.view.removeFromSuperview()
                oldViewController.removeFromParentViewController()
                detailViewController = nil
            }

            // determine the identifier of the new detail view, this is the Storyboard ID of the detail scene
            var sceneIdentifier: NSStoryboard.SceneIdentifier?
            switch tableView.clickedRow {
                case 0:
                    sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema1")
                case 1:
                    sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema2")
                case 2:
                    sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema3")
                case 3:
                    sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema4")
                case 4:
                    sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema5")
                default:
                    sceneIdentifier = nil
            }

            if sceneIdentifier != nil {
                // load the new detail controller and view from the storyboard
                detailViewController = self.storyboard?.instantiateController(withIdentifier:sceneIdentifier!) as? NSViewController
                if let newViewController = detailViewController {
                    newViewController.view.translatesAutoresizingMaskIntoConstraints = false
                    // add controller and view
                    self.addChildViewController(newViewController)
                    container.addSubview(newViewController.view)
                    // add constraints
                    let views = ["targetView": newViewController.view]
                    let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|[targetView]|",
                                                    options: [], metrics: nil, views: views)
                    let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|[targetView]|",
                                                    options: [], metrics: nil, views: views)
                    NSLayoutConstraint.activate(horizontalConstraints)
                    NSLayoutConstraint.activate(verticalConstraints)
                }
            }
        }
        else {
            print("Clicked outside the cells")
        }
    }

}

感谢您帮助我提出故事板的想法。 我制作了一个测试假人,其中有我的主视图,并制作了两个带有标签的 ViewController。 所有 ViewController 都获得了它们的 Storyboard-ID。 主视图有两个按钮,都分配给其中一个 ViewController。 通过单击它们,您将加载其中一个测试视图控制器。 我想到了这个

import Cocoa

class ViewController: NSViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}

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

func switchViews(viewNumber: Int) {
    let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil)
    var controller = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "Main"))

    switch viewNumber {
        case 1:
            print("View: 1")
            controller = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "Test1"))
        case 2:
            print("View: 2")
            controller = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "Test2"))
        default:
            print("Default");
    }

    if let window = NSApplication.shared.mainWindow {
        window.contentViewController = controller as? NSViewController
    }
}

@IBAction func buttonAction(_ sender: NSButton) {
    var viewNumber: Int = 0

    switch sender.title {
        case "controller1":
            viewNumber = 1
            print("Button: 1")
        case "controller2":
            viewNumber = 2
            print("Button2: 2")
        default:
            print("Default")
    }

    switchViews(viewNumber: viewNumber)
}

}