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 using story board in Xcode, where I have got a segue which connects the start button and the second view controller. However, there are only three different styles i.e. modal, sheet, and pop-over. I want to replace the first view controller the second one in the window. I cannot find a way to do that. I tried using a custom style for the segue, and in that use presentViewController: animator: method but I cannot figure out what to send as the argument for the animator:.
What is the simplest/proper way to transition from one view controller to the other in one window and vice versa?
Also in the storyboard when I select a view controller it shows an attribute called "Presentation" which can be multiple and single, what do those represent?
From the Library, add a button to the first View Controller and name the button, for example: Show Second View . Select the button, press and hold the Control key on the keyboard and drag from the button to the second View Controller.
Well, in addition to that, Ctrl+dragging also helps set up segues. So, Ctrl+Drag from the “Go to Other View Controller” button, to somewhere in the second View Controller. It can be anywhere in the main box of the second view controller. When you release, it will show you a box like the one below.
Specifying the Initial View Controllerstoryboard and select the Tab Bar Controller Scene. On the right, select the Attribute inspector. You'll find a checkbox named Is Initial View Controller. Checking this box will identify the selected view controller as the initial entry point for the storyboard you're on.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With