Thanks for taking your time to help others.
This is the original post, I publish here also hoping for better luck. Thanks!
Problem description:
Our SwiftUI app min deployment is iOS 14. We've been struggling with status bar color just in iOS 16.
We can't change its color/appearance from light to dark.
Previous valid solution (iOS 13 to iOS 15)
Since now we used to manage the appearance with ...
1- Call in specific view, when a condition is given, like no dark mode supported, or side menu have been open
UIApplication.setStatusBarStyle(.darkContent)
2- The extension to support this on any SwiftUI View
import UIKit
extension UIApplication {
class func setStatusBarStyle(_ style: UIStatusBarStyle) {
if let controller = UIApplication.getKeyWindow()?.rootViewController as? ContentHostingController {
controller.changeStatusBarStyle(style)
}
}
}
3- Actually, the controller class
import SwiftUI
import UIKit
class ContentHostingController: UIHostingController<AnyView> {
private var currentStatusBarStyle: UIStatusBarStyle = .default
override var preferredStatusBarStyle: UIStatusBarStyle {
currentStatusBarStyle
}
func changeStatusBarStyle(_ style: UIStatusBarStyle) {
self.currentStatusBarStyle = style
self.setNeedsStatusBarAppearanceUpdate()
}
}
But, as I said, this stopped working with iOS 16.
What we have checked?
As we googled it...
- Using .preferredColorScheme modifier, changes the app appearance, and we want to keep, for example, the dark theme along light status bar. So it's not an option.
- Applying .toolbarColorScheme (iOS 16), does nothing.
- Manage Info.plist without success. Light content by default, could be changed (with the method described above)
Questions
- Why is this not working in iOS 16? Are we doing something wrong? (worked like a charm for 13 to 15).
- Is there any generic (iOS 13 to 16) way that you actually use and work?
- (If not) Do you know any workaround to apply on 16 only?
Final solution (by @ashley-mills and refined by me):
First, a View extension to keep it clean:
func iOS16navBarAdapter(_ colorScheme: ColorScheme) -> some View {
if #available(iOS 16, *) {
return self
.toolbarBackground(Color.navigationBar, for: .navigationBar)
.toolbarBackground(.visible, for: .navigationBar)
.toolbarColorScheme(colorScheme, for: .navigationBar)
} else {
return self
}
}
You can use as follows on your view:
@State private var iOS16colorScheme: ColorScheme = .dark
...
VStack {
...
}
.iOS16navBarAdapter(iOS16colorScheme)
.onChange(of: globalSideMenu.xCoord) { value in
iOS16colorScheme = value > sideMenuOffset ? .light : .dark
}