I could help myself now. I found a solution that takes an approach that works with TabViews as well based on: https://github.com/xavierdonnellon/swiftui-statusbarstyle
My full Code Example where the states of the previous status bar styles are saved and restored upon disposal (it is important to keep an eye on the status bar style hierarchy during runtime):
ExampleApp.swift
import SwiftUI
@main
struct ExampleApp: App {
init() {
//navigation bar
let coloredNavAppearance = UINavigationBarAppearance()
coloredNavAppearance.configureWithTransparentBackground()
coloredNavAppearance.backgroundColor = .clear
coloredNavAppearance.backgroundEffect = nil
coloredNavAppearance.backgroundImage = UIImage()
coloredNavAppearance.shadowImage = UIImage()
coloredNavAppearance.shadowColor = .clear
coloredNavAppearance.titleTextAttributes = [
.foregroundColor: UIColor.black
]
coloredNavAppearance.largeTitleTextAttributes = [
.foregroundColor: UIColor.black
]
UINavigationBar.appearance().standardAppearance = coloredNavAppearance
UINavigationBar.appearance().scrollEdgeAppearance = coloredNavAppearance
UINavigationBar.appearance().compactAppearance = coloredNavAppearance
}
var body: some Scene {
WindowGroup {
RootView(content: {
ContentView()
})
}
}
}
UIApplication+StatusBarStyle.swift
extension UIApplication {
static var hostingController: HostingController<AnyView>? = nil
static var statusBarStyleHierarchy: [UIStatusBarStyle] = []
static var statusBarStyle: UIStatusBarStyle = .darkContent
///Sets the App to start at rootView
func setHostingController(rootView: AnyView) {
let hostingController = HostingController(rootView: AnyView(rootView))
windows.first?.rootViewController = hostingController
UIApplication.hostingController = hostingController
}
static func setStatusBarStyle(_ style: UIStatusBarStyle) {
statusBarStyle = style
hostingController?.setNeedsStatusBarAppearanceUpdate()
}
}
class HostingController<Content: View>: UIHostingController<Content> {
override var preferredStatusBarStyle: UIStatusBarStyle {
return UIApplication.statusBarStyle
}
}
///By wrapping views in a RootView, they will become the app's main / primary view. This will enable setting the statusBarStyle.
struct RootView<Content: View> : View {
var content: Content
init(@ViewBuilder content: () -> (Content)) {
self.content = content()
}
var body:some View {
EmptyView()
.onAppear {
UIApplication.shared.setHostingController(rootView: AnyView(content))
}
}
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@State var tabRoute = TabRoute.green
enum TabRoute: String, Identifiable {
var id: String {
self.rawValue
}
case green, black, blue, purple
static var all: [TabRoute] {
[.green, .black, .blue, .purple]
}
var bgColor: Color {
switch self {
case .green:
return .green
case .black:
return .black
case .blue:
return .blue
case .purple:
return .purple
}
}
var statusBarStyle: UIStatusBarStyle {
switch self {
case .black:
return .lightContent
default:
return .darkContent
}
}
}
var body: some View {
TabView(selection: $tabRoute) {
ForEach(TabRoute.all) { route in
NavigationView {
ViewExample(isPresented: false, title: route.rawValue, bgColor: route.bgColor, statusBarStyle: route.statusBarStyle)
.navigationTitle(route.rawValue)
.navigationBarTitleDisplayMode(.inline)
}
.navigationViewStyle(StackNavigationViewStyle())
.tabItem {
Text(route.rawValue)
}
.tag(TabRoute(rawValue: route.rawValue))
}
}
.edgesIgnoringSafeArea(.all)
}
}
struct ViewExample: View {
@Environment(\.presentationMode) var presentationMode
@State private var sheetIsPresented = false
@State var isPresented: Bool
var title: String
var bgColor: Color
@State var statusBarStyle: UIStatusBarStyle
var body: some View {
ZStack {
bgColor
}
.onAppear {
UIApplication.statusBarStyleHierarchy.append(statusBarStyle)
UIApplication.setStatusBarStyle(statusBarStyle)
}
.onDisappear {
guard UIApplication.statusBarStyleHierarchy.count > 1 else { return }
let style = UIApplication.statusBarStyleHierarchy[UIApplication.statusBarStyleHierarchy.count - 1]
UIApplication.statusBarStyleHierarchy.removeLast()
UIApplication.setStatusBarStyle(style)
}
.edgesIgnoringSafeArea(.all)
}
}