I have a Router that doesn't work in new Xcode 11, it works as an appDelegate. Now I need to transition to another SCENE and I tried all issues that I found here, but it still doesn't work. Here is the code that fails to transition to the intended next scene:
class Router {
static let shared = Router()
private init() {}
private let rootViewController: UIViewController = ViewController()
func root(_ window: inout UIWindow?) {
// need to set frame or Scene
window?.makeKeyAndVisible()
window?.rootViewController = rootViewController
}
}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
Router.shared.root(&window)
}
Related
I'm not using storyboard. I'm embedding my MainViewController into a navigation controller.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let mainVC = MainViewController(nibName: nil, bundle: nil)
let navigationController = UINavigationController(rootViewController: mainVC)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
But it's only showing black screen instead of my mainVC.
You should use window like this
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
This below code finally works for me.
In SceneDelegate,
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let rootViewController = MainViewController()
let navController: UINavigationController = UINavigationController(rootViewController: rootViewController)
self.window?.rootViewController = navController
self.window?.makeKeyAndVisible()
}
In MainViewController, this code is taken from #Kudos from comment.
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
self.navigationController?.navigationBar.isTranslucent = true // pass "true" for fixing iOS 15.0 black bg issue
self.navigationController?.navigationBar.tintColor = UIColor.white // We need to set tintcolor for iOS 15.0
appearance.shadowColor = .clear //removing navigationbar 1 px bottom border.
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
}
I am starting an app programmaticaly with no storyboards. When I try to make my UITabBarController the root view controller it looks like The background color should be red and the tab item should be a house. What could be the problem?
SceneDelegate code:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
window?.rootViewController = TabBarController()
window?.makeKeyAndVisible()
}
HomeViewController code:
import UIKit
class HomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
// Do any additional setup after loading the view.
}
}
TabBarController code:
import UIKit
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
setupTab()
}
func setupTab(){
let homeVC = HomeViewController()
homeVC.tabBarItem = UITabBarItem(title: "Home", image: UIImage(named: "House"), tag: 0)
let homeNC = UINavigationController(rootViewController: homeVC)
tabBarController?.viewControllers = [homeNC]
}
}
The work for setting up the tab view controller needs to be done while you are setting up the scene in the SceneDelegate. The HomeViewContoller's viewDidLoad was never being called.
var homeNavigationController : UINavigationController!
var secondHomeNavigationController : UINavigationController!
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
let tabBarController = TabBarController()
homeNavigationController = UINavigationController.init(rootViewController: HomeViewController())
secondHomeNavigationController = UINavigationController.init(rootViewController: HomeViewController())
tabBarController.viewControllers = [homeNavigationController, secondHomeNavigationController]
// let item1 = UITabBarItem(title: "Home", image: UIImage(named: "House"), tag: 0)
let item1 = UITabBarItem(tabBarSystemItem: .featured, tag: 0)
let item2 = UITabBarItem(tabBarSystemItem: .bookmarks, tag: 1)
homeNavigationController.tabBarItem = item1
secondHomeNavigationController.tabBarItem = item2
window?.rootViewController = tabBarController
window?.makeKeyAndVisible()
}
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
setupTab()
}
func setupTab(){
}
}
class HomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
// Do any additional setup after loading the view.
}
}
I try to set a View as first view and get a black background. But it should be red.
This is my SceneDelegate:
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = MainNavigationController()
}
This is my MainNavigationController
import UIKit
class MainNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
}
}
You just need the window to be declared with windowScene initializer instead of the frame initializer.
guard let windowScene = scene as? UIWindowScene else { return }
window = UIWindow(windowScene: windowScene)
Note: Also, make sure storyboard is disabled if you're loading rootViewController programmatically.
You need to add makeKeyAndVisible() after setting root Also assign window scene to window ...
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: UIScreen.main.bounds)
window?.windowScene = windowScene
window?.rootViewController = MainNavigationController()
window?.makeKeyAndVisible()
}
I want to insert a func(configureInitialViewController()) into willConnectTo ( so I can recall the same func in other ViewControllers )
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
configureInitialViewController()
}
func configureInitialViewController() {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
if 1>0 {
window.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: ViewController1)
} else {
window.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: ViewController2)
}
self.window = window
window.makeKeyAndVisible()
}
}
Change
func configureInitialViewController()
To
func configureInitialViewController(_ scene: UIScene)
And pass scene to it
I need to change the initial view controller based on whether voiceover is on or not. I have tried multiple ways but I always get the same error: "Value of type 'AppDelegate' has no member 'window'"
This is what I have in my didFinishLaunchingWithOptions.
print("voiceover: \(voiceOver)") // prints if voice over is on
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "voiceoverViewController")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
Value of type 'AppDelegate' has no member 'window'
You have to declare a window property manually:
var window: UIWindow?
UIApplicationDelegate is just a protocol, it doesn't declare any properties for you.
You don't have to declare window variable manually
It is available in SceneDelegate file in your project
It will have pre defined method :
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions)
Example
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
self.window = UIWindow(windowScene: windowScene)
let initialViewController =
storyboard.instantiateViewController(withIdentifier: "voiceoverViewController")
self.window!.rootViewController = initialViewController
self.window!.makeKeyAndVisible()
}
}