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()
}
}
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 not using storyboard for this application so here's my SceneDelegate willConnectTo function
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let windowScene = UIWindowScene(session: session, connectionOptions: connectionOptions)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.backgroundColor = .white
let rootViewController = PersonsViewController()
let navigationController = UINavigationController(rootViewController: rootViewController)
navigationController.navigationBar.tintColor = .black
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
self.window?.windowScene = windowScene
}
and here is the UITextView configuration function
private func configureTextView() {
textView = UITextView(frame: CGRect(x: 75, y: 120, width: view.frame.width, height: 120))
textView.font = UIFont.systemFont(ofSize: 16)
textView.textColor = .black
textView.backgroundColor = .blue
textView.delegate = self
textView.becomeFirstResponder()
textView.isUserInteractionEnabled = true
textView.keyboardType = .default
view.addSubview(textView)
}
and this is what gets printed in the console
Could not find keyboard scene delegate for interaction view <_UITextLayoutCanvasView: 0x105904be0; frame = (0 0; 375 120); userInteractionEnabled = NO; layer = <CALayer: 0x282ed8ee0>>.
2022-02-07 08:33:15.481898+0200 Project[40078:7478637] [Assert] Could not find window to attach loupe view.
I made sure that the delegate methods get called
The following code works:
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 = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: scene)
self.window?.backgroundColor = .white
let rootViewController = ViewController()
let navigationController = UINavigationController(rootViewController: rootViewController)
navigationController.navigationBar.tintColor = .black
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
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 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)
}