9

I'm changing the root view controller by pressing a button which is hooked up to a custom segue to the view controller that I want to change to. The custom segue looks like:

- (void)perform{
    UIViewController *source = (UIViewController *)self.sourceViewController;
    source.view.window.rootViewController = self.destinationViewController;
}

But this just immediately changes the root view controller. I'd like the controller to fade on top of the old controller.

user1778856
  • 641
  • 4
  • 10
  • 17
  • possible duplicate of [How do I do a Fade/No transition between view controllers](http://stackoverflow.com/questions/10961926/how-do-i-do-a-fade-no-transition-between-view-controllers) – BangOperator Apr 29 '14 at 07:29
  • your code hides the navigation bar – dev4life Sep 09 '14 at 17:51

4 Answers4

22

The common way to do that is:

    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"YourSBName" bundle:nil];
    UIViewController *vc = [sb instantiateInitialViewController];// Or any VC with Id
    DictateITAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    appDelegate.window.rootViewController = vc; // PLEASE READ NOTE ABOUT THIS LINE
    [UIView transitionWithView:appDelegate.window
                      duration:INTERVAL_DURATION
                       options:UIViewAnimationOptionTransitionCrossDissolve
                    animations:^{ appDelegate.window.rootViewController = vc; }
                    completion:nil];

Now a few notes about:

appDelegate.window.rootViewController = vc; // PLEASE READ NOTE ABOUT THIS LINE

The new view controller, you instantiate will be presented in the default orientation i.e. portrait. So probably if you do that in landscape your new view controller will appear as portrait and then turns to landscape. This line fixed this issue for me.

ilnar_al
  • 932
  • 9
  • 13
3

I think there are many answers for this already, but something like this should work:

[UIView transitionWithView:self.sourceViewController.view.window
                  duration:0.5
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    self.sourceViewController.view.window.rootViewController = self.destinationViewController;
                } completion:^(BOOL finished) {
                    // Code to run after animation
                }];
Accatyyc
  • 5,798
  • 4
  • 36
  • 51
2

I needed to translate this into Swift 3.0 for my current project. Here's a way to do that:

//Get the storyboard that contains the VC you want
let storyboard = UIStoryboard(name: "Main", bundle: nil)

//Get the VC you want to push onto the stack
//You can use storyboard.instantiateViewController(withIdentifier: "yourStoryboardId")
guard let vc = storyboard.instantiateInitialViewController() else { return }

//Get the current app delegate 
guard let appDel = UIApplication.shared.delegate as? AppDelegate else { return }

//Set the current root controller and add the animation with a
//UIView transition
appDel.window?.rootViewController = vc

UIView.transition(with: appDel.window!,
              duration: 0.25,
               options: .transitionCrossDissolve,
            animations: { appDel.window?.rootViewController = vc } ,
            completion: nil)
-3

The easiest way is:

[sourceViewController presentViewController:destinationViewController animated:YES completion:nil];

More about it: https://developer.apple.com/library/ios/featuredarticles/viewcontrollerpgforiphoneos/ModalViewControllers/ModalViewControllers.html

Rakib Ansary
  • 4,078
  • 2
  • 18
  • 29
dev4life
  • 10,785
  • 6
  • 60
  • 73
  • This does not change the root view controller, it adds a new view controller to the stack. You will not free memory using this method several times. – LightMan Jul 13 '15 at 19:00