I have following code in my AppDelegate.swift to setup root view controller for an iOS application. But it does not work. It follows Target structure (defined under General
For Xcode 11+ and Swift 5+ inside SceneDelegate.swift
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let submodules = (
home: HomeRouter.createModule(),
search: SearchRouter.createModule(),
exoplanets: ExoplanetsRouter.createModule()
)
let tabBarController = TabBarModuleBuilder.build(usingSubmodules: submodules)
window.rootViewController = tabBarController
self.window = window
window.makeKeyAndVisible()
}
}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
self.window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout()
let swipingController = SwipingController(collectionViewLayout: layout)
self.window?.rootViewController = swipingController
}
I tried the following approach and it's working for me in iOS 13 and also tested on iOS 12.4.2 from Xcode 11.
func resetRoot() {
guard let rootVC = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController") as? ViewController else {
return
}
let navigationController = UINavigationController(rootViewController: rootVC)
UIApplication.shared.windows.first?.rootViewController = navigationController
UIApplication.shared.windows.first?.makeKeyAndVisible()
}
If you don't want to use main storyboard, if you want to create you own views programmatically.
For xcode 11.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
window?.makeKeyAndVisible()
window?.rootViewController = UINavigationController(rootViewController: ViewController())
}
This will defenetily work. Thanks
I did two things. Firstly I set a Notification
into SceneDelegate
, then when I needed to change the RootViewController
I did a Notification Post
and it worked. But it's an anwful solution.
My boss recommended me to change the Controllers
of the NavigationController
, something like this:
func logged() {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "MainTabViewController", bundle: nil)
let mainVC = mainStoryboard.instantiateInitialViewController()
self.navigationController?.setViewControllers([mainVC!], animated: false)
}
I know that perhaps it's not the best solution, but I see it cleaner.
I'm working now on iOS 13 and I didn't want to use deprecated
things.
Here's what work for both iOS 13.x and iOS 12.x and below
For iOS 13,In the Scene Delegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)
//Make sure to do this else you won't get
//the windowScene object using UIApplication.shared.connectedScenes
self.window?.windowScene = windowScene
let storyBoard: UIStoryboard = UIStoryboard(name: storyBoardName, bundle: nil)
window?.rootViewController = storyBoard.instantiateInitialViewController()
window?.makeKeyAndVisible()
}
In a utility class, I wrote below function to get the window
object and assign it to the appdelegate.window
. According to my needs, I needed to set root view controller at multiple places in different scenarios for which I needed the window object.
static func redirectToMainNavRVC(currentVC: UIViewController){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let vc = UIStoryboard(name: appDelegate.storyBoardName, bundle: nil).instantiateViewController(withIdentifier: "MainNavigationViewController") as! MainNavigationViewController
if #available(iOS 13.0, *){
if let scene = UIApplication.shared.connectedScenes.first{
guard let windowScene = (scene as? UIWindowScene) else { return }
print(">>> windowScene: \(windowScene)")
let window: UIWindow = UIWindow(frame: windowScene.coordinateSpace.bounds)
window.windowScene = windowScene //Make sure to do this
window.rootViewController = vc
window.makeKeyAndVisible()
appDelegate.window = window
}
} else {
appDelegate.window?.rootViewController = vc
appDelegate.window?.makeKeyAndVisible()
}
}
This worked well for me. Hopefully, it works for others too.