首页 > 解决方案 > Cocoa,Swift 4 - 当它的故事板与应用程序的 Main.Storyboard 不同时,如何以非编程方式嵌入自定义 NSViewController?

问题描述

我正在更新 Swift 4/Xcode 12 中的 MacOS 程序。我有一个自定义视图控制器“HelloWorldViewController”,之前我自己在窗口中显示。HelloWorldViewController 使用故事板 HelloWorldViewController.storyboard 而不是 Main.Storyboard。这是用于切换包含工作得很好的视图的窗口的代码。

    func toggleHelloWorldWindow() {
        
        if helloWorldViewCtrl == nil {
           
            let myStoryboard = NSStoryboard(name: NSStoryboard.Name("HelloWorldView"), bundle: nil)
            helloWorldWindowCtrl = myStoryboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("HelloWorldWindow")) as? NSWindowController

            guard helloWorldWindowCtrl != nil else {return}
            helloWorldViewCtrl = helloWorldWindowCtrl!.window!.contentViewController as? HelloWorldViewController
        }
        
        if let myWindowController = helloWorldWindowCtrl {
            
            if myWindowController.window!.isVisible {
                myWindowController.window!.orderOut(self)
            } else {
                myWindowController.showWindow(helloWorldWindowCtrl)
            }
        }
    }

但是,我决定使用控制器的最佳方式是将其嵌入到主应用程序中,而不是单独的窗口中。似乎这样做的方法是使用一个 NSContainerView ,如果我在与主应用程序相同的故事板文件中拥有自定义视图的故事板,我就能正常工作。

但在我的一生中,我一直无法让它指向外部故事板。当我在自定义视图页面上为项目设置值时,它总是在自定义视图控制器的 viewDidLoad 中崩溃,因为它们都是 nil (即视图没有呈现?)

class HelloWorldViewController: NSViewController {
    
    @IBOutlet weak var helloWorld: NSTextField!
    
    override func viewDidLoad() {

        super.viewDidLoad()        
        helloWorld.stringValue = "Hello world..." (crashes)
    }    
}

经过两天的大惊小怪,它能够以编程方式工作(这对我的目的来说很好,并且可能是我会坚持的解决方案)但我仍然想知道我在尝试做的过程中缺少什么只有故事板?我试图设置一个 segue,但找不到任何方法来告诉它故事板文件名,并且仅使用场景标识符导致了同样的崩溃。

(主应用程序的 viewDidLoad() 中的程序版本可以正常工作)

       let myStoryboard = NSStoryboard(name: NSStoryboard.Name("HelloWorldView"), bundle: nil)
        
        if let helloWorldWindowCtrl = myStoryboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("HelloWorldWindow")) as? NSWindowController,
           let controller = helloWorldWindowCtrl.window!.contentViewController as? HelloWorldViewController
        {
            addChild(controller)
            controller.view.translatesAutoresizingMaskIntoConstraints = false
            helloWorldView.addSubview(controller.view)
      
            NSLayoutConstraint.activate([
                controller.view.leadingAnchor.constraint(equalTo: helloWorldView.leadingAnchor, constant: 0),
                controller.view.trailingAnchor.constraint(equalTo: helloWorldView.trailingAnchor, constant: 0),
                controller.view.topAnchor.constraint(equalTo: helloWorldView.topAnchor, constant: 0),
                controller.view.bottomAnchor.constraint(equalTo: helloWorldView.bottomAnchor, constant: 0)
            ])
        }

标签: swiftxcodecocoacontainer-view

解决方案


推荐阅读