【问题标题】:Transitioning between view controller, OS X在视图控制器、OS X 之间转换
【发布时间】:2015-04-11 19:41:32
【问题描述】:

我正在尝试编写一个单窗口计时器应用程序,当用户按下开始按钮时,我希望它显示另一个带有倒计时等的视图控制器。我还在 Xcode 中使用故事板,我有一个 segue它连接开始按钮和第二个视图控制器。但是,只有三种不同的样式,即模态、表单和弹出式。我想将第一个视图控制器替换为窗口中的第二个。我找不到办法做到这一点。我尝试为 segue 使用自定义样式,并在其中使用 presentViewController: animator: 方法,但我无法弄清楚要发送什么作为 animator: 的参数。

在一个窗口中从一个视图控制器转换到另一个视图控制器的最简单/正确的方法是什么?反之亦然?

同样在故事板中,当我选择一个视图控制器时,它会显示一个名为“Presentation”的属性,它可以是多个也可以是单个,它们代表什么?

【问题讨论】:

    标签: objective-c xcode macos cocoa swift


    【解决方案1】:

    我认为最简单的方法是交换contentViewControllerNSWindow

    // in NSViewController's subclass
    @IBAction func someAction(sender: AnyObject) {
        let nextViewController = ... // instantiate from storyboard or elsewhere
    
        if let window = view.window where window.styleMask & NSFullScreenWindowMask > 0 {
            // adjust view size to current window
            nextViewController.view.frame = CGRectMake(0, 0, window.frame.width, window.frame.height)
        }
    
        view.window?.contentViewController = nextViewController
    }
    

    这是选项#1。

    如果你想使用 segue,创建一个自定义的,并将其设置为 IB 中带有标识符的 segue 类。

    class ReplaceSegue: NSStoryboardSegue {
        override func perform() {
            if let fromViewController = sourceController as? NSViewController {
                if let toViewController = destinationController as? NSViewController {
                    // no animation.
                    fromViewController.view.window?.contentViewController = toViewController
                }
            }
        }
    }
    

    这是选项#2。

    最后一个选项是使用presentViewController:animator:NSViewController。下面的代码是自定义 NSViewControllerPresentationAnimator 用于溶解动画。

    class ReplacePresentationAnimator: NSObject, NSViewControllerPresentationAnimator {
        func animatePresentationOfViewController(viewController: NSViewController, fromViewController: NSViewController) {
            if let window = fromViewController.view.window {
                NSAnimationContext.runAnimationGroup({ (context) -> Void in
                    fromViewController.view.animator().alphaValue = 0
                }, completionHandler: { () -> Void in
                    viewController.view.alphaValue = 0
                    window.contentViewController = viewController
                    viewController.view.animator().alphaValue = 1.0
                })
            }
        }
    
        func animateDismissalOfViewController(viewController: NSViewController, fromViewController: NSViewController) {
            if let window = viewController.view.window {
                NSAnimationContext.runAnimationGroup({ (context) -> Void in
                    viewController.view.animator().alphaValue = 0
                    }, completionHandler: { () -> Void in
                        fromViewController.view.alphaValue = 0
                        window.contentViewController = fromViewController
                        fromViewController.view.animator().alphaValue = 1.0
                })
            }        
        }
    }
    

    那就这样介绍VC吧。

    @IBAction func replaceAction(sender: AnyObject) {
        let nextViewController = ... // instantiate from storyboard or elsewhere
        presentViewController(nextViewController, animator: ReplacePresentationAnimator())
    }
    

    要解雇,请在提供的 VC 中致电 presentingViewControllerdismissViewController:

    @IBAction func dismissAction(sender: AnyObject) {
        presentingViewController?.dismissViewController(self)    
    }
    

    Swift4 版本

    class ReplacePresentationAnimator: NSObject, NSViewControllerPresentationAnimator {
    func animatePresentation(of viewController: NSViewController, from fromViewController: NSViewController) {
        if let window = fromViewController.view.window {
            NSAnimationContext.runAnimationGroup({ (context) -> Void in
                fromViewController.view.animator().alphaValue = 0
            }, completionHandler: { () -> Void in
                viewController.view.alphaValue = 0
                window.contentViewController = viewController
                viewController.view.animator().alphaValue = 1.0
            })
        }
    }
    
    func animateDismissal(of viewController: NSViewController, from fromViewController: NSViewController) {
        if let window = viewController.view.window {
            NSAnimationContext.runAnimationGroup({ (context) -> Void in
                viewController.view.animator().alphaValue = 0
            }, completionHandler: { () -> Void in
                fromViewController.view.alphaValue = 0
                window.contentViewController = fromViewController
                fromViewController.view.animator().alphaValue = 1.0
            })
        }
    }
    

    }

    希望对您有所帮助。

    【讨论】:

    • 我发现选项 1 在全屏模式下不起作用
    • @jiminybob99 感谢您的报告!我更新了答案。
    【解决方案2】:

    如果你有一个父视图控制器,你可以给它分配子视图控制器,并使用transition 方法。示例代码,放置在父视图控制器的viewDidLoad中:

    if let firstController = self.storyboard?.instantiateController(withIdentifier: "firstController") as? NSViewController {
        firstController.view.autoresizingMask = [.width, .height]
        firstController.view.frame = self.view.bounds
        self.addChild(firstController)
        self.view.addSubview(firstController.view)
    }
    
    if let secondController = self.storyboard?.instantiateController(withIdentifier: "secondController") as? NSViewController {
        self.addChild(secondController)
    }
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        if let firstController = self.children.first, let secondController = self.children.last {
            self.transition(from: firstController, to: secondController, options: .crossfade, completionHandler: nil)
        }
    }
    

    必须将第一个子控制器的视图作为子视图添加到父控制器的视图中,否则transition 方法不起作用。

    在上面的示例中,故事板与一个主视图控制器(= self)、一个故事板 ID 为“firstController”的子视图控制器和另一个故事板 ID 为“secondController”的子视图控制器一起使用

    【讨论】:

    • 回答三年前的一个问题。你真的是一个善良的撒玛利亚人,而不是在寻找那个好的旧业力!我无法对此进行测试,因为三年来没有做过 iOS/macOS 开发,但希望这能帮助现在面临这个问题的其他人。
    • @user14492:实际上我自己也在寻找答案。我看到 StackOverflow 中的示例都没有使用现代 transition 方法,所以在弄清楚该方法的实际工作原理后,我无法阻止自己撰写答案:)
    • 感谢您的努力和分享。那时我实际上无法弄清楚。很高兴知道这只是我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多