Search code examples
tvosuiwindow

Custom UIWindow in tvOS makes app unresponsive to keyboard input


In tvOS, if I use a custom UIWindow instance, the app stops responding to the keyboard and remote in the simulator. Is there any variable or property that I should set on the UIWindow instance?

class AppDelegate: UIResponder, UIApplicationDelegate {

    lazy var window : UIWindow? = {
        let screen = UIScreen.main
        let w = UIWindow(frame: screen.bounds)
        return w
    }()

    // ...
}

The reason is that I need to subclass UIWindow to have custom tint colors and to respond to Dark/Light mode changes via traitCollectionDidChange.

This was in tvOS 10.2.1


Solution

  • Apparently one would need to instantiate the storyboard and present the window as well if a custom UIWindow is required. Simply providing a UIWindow instance would not be sufficient.

    First, remove the key UIMainStoryboardFile from the Info.plist file of your main app.

    Then add in code to in the application did launch handler to:

    1. Instantiate the window and assign to the app delegate's property.
    2. Instantiate the storyboard.
    3. Instantiate the initial view controller
    4. Assign the view controller to the window.
    5. Show the window.
        @UIApplicationMain
        class AppDelegate: UIResponder, UIApplicationDelegate {
    
            var window : UIWindow?
    
            // ...
    
            func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
                window = MainWindow(frame: UIScreen.main.bounds)
                // We need to instantiate our own storyboard instead of specifying one in `Info.plist` since we need our own custom `UIWindow` instance.
                // Otherwise if we just create the custom UIWindow instance and let the system creates a storyboard,
                // then the application won't respond to the keyboard/remote (user input).
                let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
                window?.rootViewController = storyboard.instantiateInitialViewController()
                defer {
                    window?.makeKeyAndVisible()
                }
    
                // ... All other setup code
            }
    
            // ...
    
        }