Search code examples
iosswiftuiwindowios7-statusbar

Hide status bar but not custom UIWindow


I have a custom UIWindow that is my own status bar, so I want to hide the status bar and show mine instead. I have

override var prefersStatusBarHidden: Bool {
    return true
}

In both my UIWindow's rootViewController and the main ViewController. This hides the status bar, but it also hides my UIWindow. My UIWindow's windowLevel is UIWindowLevelStatusBar + 1, but I tested other windowLevels and it was hidden regardless of the level.

Setting an opaque background for my custom UIWindow is not an option.

How can I hide the status bar but not my custom UIWindow?


Solution

  • Edit: better solution

    The same still holds true as before/below, but the actual code is shorter, simpler, and more Swifty.

    In your AppDelegate, have

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        myStatusBarWindow.isHidden = false
        return true
    }
    

    And, of course, hide the system status bar. Either do this in the build settings or info.plist, or in your view controller, say

    override var prefersStatusBarHidden: Bool {
        return true
    }
    

    Much better :)


    Old solution

    Unfortunately, I cannot find what is probably the best answer, but I have a workaround:

    First show your window. Only after that should you hide the status bar. I am not sure why this works, but it does. You can do that like this:

    // Class var 
    var statusBarHidden = false
    
    // For example in viewDidLoad but only the order matters
    override func viewDidLoad() {
        myWindow.isHidden = false
        statusBarHidden = true
        setNeedsStatusBarAppearanceUpdate()
    }
    
    override var prefersStatusBarHidden: Bool {
        return statusBarHidden
    }
    

    Through my experimentation I discovered that prefersStatusBarHidden is checked before viewDidLoad. Thus, we need to tell the view controller to check again once the window is shown. Again, I don't know why this works, but it does. If anyone can explain this phenomenon (why this order matters), that would be an excellent supplement to this solution.