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
What Is the Swift Syntax " .Bar" Called
How to Cycle Through the Entire Alphabet with Swift While Assigning Values
How May I Test the Equivalency of Enumeration Cases with Associated Values in Swift 4
How to Get the Index of the Element in the List in Swiftui When the List Is Populated with the Array
Transparent Background for Texteditor in Swiftui
Swift Date(Byadding:To:) Returns Nil for Trivial Calculation in Repl
Array of Nested Type: Why Does the Compiler Complain
Trying to Know When a Window Closes in a MACos Document Based Application
Initialize Class-Instance and Access Variables in Swift
What Is Preventing My Conversion from String to Int When Decoding Using Swift 4's Codable
Custom Segue Transition Animation
Swiftui iOS 14 Widget Countdown
How to Return Value from Async Block in Swift
Firebase Query Ordering Not Working Properly
Simple Swift Fibonacci Program Crashing (Project Euler 2)
How to Properly Use Queryorderedbyvalue
Swift Custom Context Menu Previewprovider Can Not Click Any View Inside(Using Tapgesture)