'iOS 13 Status bar style invalid (childForStatusBarStyle never called)
I've been searching a lot, but didn't find the same problem as my on StackOverflow or anywhere else.
Setup
Info.plist
ViewControllerBasedStatusBar
set toYES
StatusBarStyle
set to.lightContent
UserInterfaceStyle
set to.light
(app doesn't support.dark
mode)
- Each
UIViewController
has its own implementation ofpreferredStatusBarStyle
:override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
UITabBarController
hasextension
:open override var childForStatusBarStyle: UIViewController? { return selectedViewController }
UINavigationController
hasextension
:override open var childForStatusBarStyle: UIViewController? { return topViewController }
Problem
Since iOS 13 released my status bar logic was broken and I can't understand why. On iOS <= 12.4 everything works properly. .childForStatusBarStyle
is never called and each viewController has some random style
UPDATE: Since iOS 13 released status has style based on UserInterfaceStyle
set global, not based on preferredStatusBarStyle
(with proper setup) in case of UITabBarController
-> UINavigationController
-> UIViewController
hierarchy.
Question
The question is how to solve this problem? Did something silently changed in this logic? (Checked many articles and changelogs)
Reproduction
I've been able to reproduce the bug in the sample project with everything set up as mentioned above.
Here I have github project which contains view hierarchy as follows:
CustomTabBarController
- UINavigationController
- CustomViewController
- CustomViewController
Now, when you select the first tab app has dark style status bar, when the second selected light style one. CustomViewController has preferredStatusBarStyle
set to .lightContent
.
More:
- Xcode: Version 11.5 (11E608c)
- Device: iPhone 8 Simulator
- iOS: Version 13.5
P.S: I'm ready and will provide more details on the topic, don't hesitate to ask me to do so. Project is running more than 2 years and thing like this is really to debug :)
Solution 1:[1]
In a navigation controller situation, the status bar style (light/dark) does not depend, and has never depended, on anything except the navigation bar style. Add this line in your project's custom tab bar:
let bugVC = UINavigationController(rootViewController: ViewController())
bugVC.navigationBar.barStyle = .black // *
Now the status bar text is white in both of the tab bar controller's children. (And if you then don't like the color of the navigation bar, which is the default black, you can change it; that won't affect the behavior of the status bar.)
Solution 2:[2]
For those to whom using .barStyle
is a big deal in case of time, there is a workaround. Subclass UINavigationController
, then call setNeedsStatusBarAppearanceUpdate
each time viewControllers
change.
Sample code
class WorkaroundNavigationController: UINavigationController {
override var childForStatusBarStyle: UIViewController? {
return topViewController
}
override var viewControllers: [UIViewController] {
didSet { setNeedsStatusBarAppearanceUpdate() }
}
}
Solution 3:[3]
For UINavigationController
- UIViewController
structure, add code below to navigation controller. Then override child view controller's preferredStatusBarStyle
, it worked for me.
override var childForStatusBarStyle: UIViewController? {
visibleViewController
}
override var preferredStatusBarStyle: UIStatusBarStyle {
visibleViewController?.preferredStatusBarStyle ?? .default
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | matt |
Solution 2 | ???? |
Solution 3 |