【问题标题】:Swift: Switch between NSViewController inside Container View / NSViewSwift:在 Container View / NSView 内的 NSViewController 之间切换
【发布时间】:2017-04-08 23:39:30
【问题描述】:

我想完成一个非常简单的任务——通过按一个按钮来更改容器视图的ViewController:

在我的示例中,ViewController1 使用 Interface Builder 嵌入到容器视图中。通过按下按钮ViewController2,我想将视图更改为第二个 ViewController。

我很困惑,因为如果我创建一个 Outlet,Container View 本身似乎是 NSView,而且据我所知 NSView 不能包含 VC。非常感谢您的帮助!

【问题讨论】:

    标签: swift storyboard segue nsview nsviewcontroller


    【解决方案1】:

    请注意,为了使其工作,您必须将情节提要标识符添加到您的视图控制器,这可以通过转到您的情节提要,然后在右侧窗格中选择身份检查器,然后在 @ 中输入 Storyboard ID 987654322@子类。

    然后ViewController 的这种实现将实现您正在寻找的东西。

    import Cocoa
    
    class ViewController: NSViewController {
    
        // link to the NSView Container
        @IBOutlet weak var container : NSView!
    
        var vc1 : ViewController1!
        var vc2 : ViewController2!
    
        var vc1Active : Bool = false
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Make sure to set your storyboard identiefiers on ViewController1 and ViewController2
            vc1 = NSStoryboard(name: "name", bundle: nil).instantiateController(withIdentifier: "ViewController1") as! ViewController1
            vc2 = NSStoryboard(name: "name", bundle: nil).instantiateController(withIdentifier: "ViewController2") as! ViewController2
    
            self.addChild(vc1)
            self.addChild(vc2)
            vc1.view.frame = self.container.bounds
            self.container.addSubview(vc1.view)
            vc1Active = true
    
        }
    
        // You can link this action to both buttons
        @IBAction func switchViews(sender: NSButton) {
    
            for sView in self.container.subviews {
                sView.removeFromSuperview()
            }
    
            if vc1Active == true {
    
                vc1Active = false
                vc2.view.frame = self.container.bounds
                self.container.addSubview(vc2.view)
    
            } else {
    
                vc1Active = true
                vc1.view.frame = self.container.bounds
                self.container.addSubview(vc1.view)
            }
    
        }
    }
    

    【讨论】:

    • 感谢@Wes 的详细回答!我在self.container.addSubview(vc1.view) 行中有一个错误:»容器视图中有意外的子视图«。因此,我尝试删除所有子视图(就像您首先在您的 func switchViews 中所做的那样,但它没有用(错误保持不变)。有什么想法吗?
    • @ixany 一些事情。首先,更改您的代码以反映我所做的编辑(进行细微更改以防止混淆视图)。另外,删除Container 和ViewController1 之间的嵌入关系。通过在 IB 中右键单击 Container 并删除连接来执行此操作。
    • 再次感谢@Wes!你是对的,我不得不在 IB 中删除 ViewController1 的嵌入/segue。我接受了您的回答,但还有一个问题:为此任务添加和删除子视图是最佳做法吗?在实现它的同时,我还发现了.removeChildViewController(),并认为它在性能方面可能会更好。在子视图解决方案中,应用程序会加载所有可能的 VC,即使它们永远不会出现。添加/删除子视图还有其他优势吗?
    • 这样,一切都已经计算过了,并且在您需要资源之前就已经加载了资源,因此在最后一秒不会进行计算/资源加载。话虽如此,您是对的,如果您可能永远不需要某个 vc,这不是最好的方法,最好仅在需要时才在加载时懒惰地声明它们,然后将它们拆除。但是,如果您确定需要这些控制器,则将两个控制器的引用保持在非常小的性能负载并且可以预加载可以提供一些小的性能提升。
    • @Wes @ixany 我知道已经有一段时间了,但我喜欢这个解决方案,但我一直收到以下错误,想知道你是否知道如何解决它:Ambiguous use of 'instantiateController(identifier:creator:)'。然后当我点击它时,找到了两个候选人,都是AppKit.NSStoryBoard
    【解决方案2】:

    也许这是一个迟到的答案,但无论如何我都会发布我的解决方案。希望它可以帮助某人。

    我在 ContainerView 中嵌入了 NSTabViewController。然后,为了不看到顶部的标签,我这样做了:

    • 转到情节提要中的 NSTabViewController

    • 在属性检查器中将样式更改为未指定

    • 然后点击Tab Bar View Controller中的TabView,并将样式设置为“tabless”:

    在此之后,您需要:

    • 将 tabViewController 引用存储到 mainViewController 以便从代码中选择选项卡
    • 向 mainViewController(您的容器所在的位置)添加一个按钮,您将使用该按钮更改 tabViewController 中的选项卡。

    您可以通过在覆盖为 segue 函数做准备时存储对 tabViewController 的引用来做到这一点。这是我的代码:

    首先给mainViewController添加属性

    private weak var tabViewController: NSTabViewController?
    

    然后重写此函数并保留对 tabViewController 的引用:

        override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
                guard let tabViewController = segue.destinationController
                    as? NSTabViewController else { return }
    
                **self.tabViewController = tabViewController as? NSTabViewController**
    
            }
    

    在此之后,您将参考所有设置的 tabViewController。 接下来(最后)要做的事情是对按钮进行操作,以便移动到第一个(或第二个)视图控制器,如下所示:

    @IBAction func changeToSecondTab(_ sender: Any) {
            self.tabViewController?.selectedTabViewItemIndex = 0 // or 1 for second VC 
        } 
    

    一切顺利!

    【讨论】:

      猜你喜欢
      • 2011-09-07
      • 2022-08-08
      • 1970-01-01
      • 2017-11-09
      • 2018-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多