Transitioning between view controller, OS X

前端 未结 2 1721
南旧
南旧 2020-12-13 04:19

I am trying to write a single window timer application, where when the user presses the start button I want it to show another view controller with countdown etc. I\'m also

2条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-13 05:23

    I think the simplest way is that swapping contentViewController of NSWindow.

    // 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
    }
    

    This is option #1.

    If you want to use segue, create custom one and set it to segue class with identifier in IB.

    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
                }
            }
        }
    }
    

    This is option #2.

    Last option is using presentViewController:animator: of NSViewController. The code below is custom NSViewControllerPresentationAnimator for dissolve animation.

    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
                })
            }        
        }
    }
    

    Then present VC like this.

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

    For dismissal, call presentingViewController's dismissViewController: in the presented VC.

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

    Swift4 Version

    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
            })
        }
    }
    

    }

    Hope this help.

提交回复
热议问题