Im trying to swap to another root view controller with a tab bar; via app delegate, and I want to add transition animation. By default it would only show the view without any animation.
let tabBar = self.instantiateViewController(storyBoard: "Main", viewControllerID: "MainTabbar")
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window = UIWindow(frame: UIScreen.main.bounds)
appDelegate.window?.rootViewController = tabBar
appDelegate.window?.makeKeyAndVisible()
That's how I swapped to another rootview controller.
I evaluated UIView.transition(from: view, to: view)
and UIView.transition(with: view)
some time ago and ended up using this: (but unfortunately can't remember why)
guard let window = UIApplication.shared.keyWindow else {
return
}
guard let rootViewController = window.rootViewController else {
return
}
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MainTabbar")
vc.view.frame = rootViewController.view.frame
vc.view.layoutIfNeeded()
UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
window.rootViewController = vc
}, completion: { completed in
// maybe do something here
})
Try this:
UIView.transition(from: appdelegate.window.rootViewController!.view, to: tabbar.view, duration: 0.6, options: [.transitionCrossDissolve], completion: {
_ in
appdelegate.window.rootViewController = tabbar
})
Im trying to swap to another root view controller ... and I want to add transition animation
I have an app that does this: it changes the root view controller with animation (it's called Albumen).
But my app actually doesn't actually change the root view controller. The root view controller is a custom container view controller that never changes. Its view is never seen and it has no functionality. Its only job is to be the place where the change happens: it swaps one child view controller for another — and thus the transition animation works.
In other words, you add one view controller to your view controller hierarchy, right at the top of the hierarchy, and the whole problem is solved neatly and correctly.
An alternative solution:
let stb = UIStoryboard(name: "YOUR_STORYBOARD_NAME", bundle: nil)
let rootVC = stb.instantiateViewController(withIdentifier: "YOUR_TABBAR_VIEWCONTROLLER_NAME")
let snapshot = (UIApplication.shared.keyWindow?.snapshotView(afterScreenUpdates: true))!
rootVC.view.addSubview(snapshot);
UIApplication.shared.keyWindow?.rootViewController = rootVC;
UIView.transition(with: snapshot, duration: 0.4, options: .transitionCrossDissolve, animations: {
snapshot.layer.opacity = 0;
}, completion: { (status) in
snapshot.removeFromSuperview()
})
Swift 4
Paste function into AppDelegate
:
func setRootViewController(_ vc: UIViewController, animated: Bool = true) {
guard animated, let window = self.window else {
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
return
}
window.rootViewController = vc
window.makeKeyAndVisible()
UIView.transition(with: window,
duration: 0.3,
options: .transitionCrossDissolve,
animations: nil,
completion: nil)
}
I have created a helper class for this based on d.felber's answer:
import UIKit
class ViewPresenter {
public static func replaceRootView(for viewController: UIViewController,
duration: TimeInterval = 0.3,
options: UIView.AnimationOptions = .transitionCrossDissolve,
completion: ((Bool) -> Void)? = nil) {
guard let window = UIApplication.shared.keyWindow else {
return
}
guard let rootViewController = window.rootViewController else {
return
}
viewController.view.frame = rootViewController.view.frame
viewController.view.layoutIfNeeded()
UIView.transition(with: window, duration: duration, options: options, animations: {
window.rootViewController = viewController
}, completion: completion)
}
}
You can use it like this:
let loginVC = SignInViewController(nibName: "SignInViewController", bundle: nil)
ViewPresenter.replaceRootView(for: loginVC)
or
ViewPresenter.replaceRootView(for: loginVC, duration: 0.3, options: .transitionCrossDissolve) {
(bool) in
// do something
}
来源:https://stackoverflow.com/questions/41144523/swap-rootviewcontroller-with-animation