【问题标题】:macOS - Swift 4.0 Container View does not show NSViewmacOS - Swift 4.0 容器视图不显示 NSView
【发布时间】:2018-04-23 09:09:02
【问题描述】:

我正在使用 Swift 4.0 和 目前我正在为我的容器视图而苦苦挣扎。

I've this layout

Layout while running the app

问题是,当我单击其中一个 TableView 项目时,我的容器视图不会加载带有“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,但没有任何迹象表明我的情况。

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

【问题讨论】:

  • 是否要自行替换视图?
  • 我想将 Thema1 视图放在容器视图中。未来会有更多的视图,a.e Thema2, Thema3 等等。关于您单击哪个表视图项,相关的 ThemaX 视图应放置在容器视图中。
  • 您想使用Thema1 的新实例还是从情节提要加载视图控制器?
  • 我认为使用新实例会更好。
  • 新的Thema1 不包含“THEMA 1”标签。我正在寻找教程或示例。

标签: swift macos view containers nsview


【解决方案1】:

我找到了示例代码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")
        }
    }

}

【讨论】:

    【解决方案2】:

    感谢您帮助我完成故事板创意。 我做了一个测试假人,在那里我有我的主视图并制作了两个带有标签的 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)
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2020-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多