Hello! Thanks for taking your time to help others.
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.
(*) For instance, this picture refers to what I think is status bar (may be obvious, yes).
Previous valid solution (iOS 13 to iOS 15)
Since now we used to manage the appearance with ...
- Call in specific view, when a condition is given, like no dark mode supported, or side menu have been open
UIApplication.setStatusBarStyle(.darkContent)
- 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)
}
}
}
- 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):
You can also check at StackOverflow
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
}