Swap Rootviewcontroller With Animation

Swap rootViewController with animation?

You can use UIView.transition(with: view) to replace the rootViewController of a UIWindow:

guard let window = UIApplication.shared.keyWindow else {
return
}

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MainTabbar")

// Set the new rootViewController of the window.
// Calling "UIView.transition" below will animate the swap.
window.rootViewController = vc

// A mask of options indicating how you want to perform the animations.
let options: UIView.AnimationOptions = .transitionCrossDissolve

// The duration of the transition animation, measured in seconds.
let duration: TimeInterval = 0.3

// Creates a transition animation.
// Though `animations` is optional, the documentation tells us that it must not be nil. ¯\_(ツ)_/¯
UIView.transition(with: window, duration: duration, options: options, animations: {}, completion:
{ completed in
// maybe do something on completion here
})

Swapping rootViewController with animation

transitionWithView is intended to animate subviews of the specified container view. It is not so simple to animate changing the root view controller. I've spent a long time trying to do it w/o side effects. See:

Animate change of view controllers without using navigation controller stack, subviews or modal controllers?

EDIT: added excerpt from referenced answer

[UIView transitionFromView:self.window.rootViewController.view
toView:viewController.view
duration:0.65f
options:transition
completion:^(BOOL finished){
self.window.rootViewController = viewController;
}];

RootViewController Switch Transition Animation

You can wrap the switching of the rootViewController in a transition animation block:

[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ self.window.rootViewController = newViewController; }
completion:nil];

Change RootViewcontroller with the Push Transition effect

Based on this Apple's documentation

UIViewController *viewControllerToBeShown=[[UIViewController alloc]init];

//viewControllerToBeShown.view.frame = self.view.frame;

viewControllerToBeShown.view.backgroundColor = [UIColor orangeColor];



AppDelegateClass *yourAppDelegate =(AppDelegateClass*)[UIApplication sharedApplication].delegate;


UIView *myView1 = yourAppDelegate.window.rootViewController.view;

UIView *myView2 = viewControllerToBeShown.view;

myView2.frame = yourAppDelegate.window.bounds;


[yourAppDelegate.window addSubview:myView2];


CATransition* transition = [CATransition animation];
transition.startProgress = 0;
transition.endProgress = 1.0;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
transition.duration = 5.0;

// Add the transition animation to both layers
[myView1.layer addAnimation:transition forKey:@"transition"];
[myView2.layer addAnimation:transition forKey:@"transition"];

myView1.hidden = YES;
myView2.hidden = NO;


yourAppDelegate.window.rootViewController = viewControllerToBeShown;

Swift

        guard let appDelegate = UIApplication.shared.delegate,
let appDelegateWindow = appDelegate.window,
let appDelegateView = window.rootViewController?.view,
let viewContollersView = viewController.view else {
return
}
viewContollersView.frame = (appDelegateWindow?.bounds)!
appDelegate.window??.addSubview(viewContollersView)
let transition = CATransition()
transition.startProgress = 0
transition.endProgress = 1.0
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
transition.duration = 0.35
appDelegateView.layer.add(transition, forKey: "transition")
viewContollersView.layer.add(transition, forKey: "transition")
appDelegateView.isHidden = true
viewContollersView.isHidden = false
appDelegateWindow?.rootViewController = viewController

Replacing the UIWindow's rootViewController while using a transition, appears to be leaking

I logged that bug report; I have had no response from Apple engineering on it.

The sample code I submitted with the bug report demonstrating the issue is at https://github.com/adurdin/radr21404408

As far as I am aware, the issue is still present in current versions of iOS, but I have not tested exhaustively. Who knows, perhaps 9.3 beta fixes it? :)

In the application where I encountered this bug, we had been using custom transitions and rootViewController replacement for the majority of screen transitions. I have not found a solution to this leak, and because of reasons could not easily remove all the rootViewController manipulation, so instead worked around the issue by minimising where we used presentViewController and friends, and carefully managing the places where we required it.

One approach that I think has potential to avoid the bug while still retaining similar capabilities to rootViewController swapping--but have not yet implemented--is to have the rootViewController be a custom container view controller that occupies the full screen, and defines a presentation context. Instead of swapping the window's rootViewController, I would swap the single child view controller in this container. And because the container defines the presentation context, the presentations will occur from the container instead of the child being swapped. This should then avoid the leaks.



Related Topics



Leave a reply



Submit