iOS16: preferredStatusBarStyle of UIHostingController is ignored

My SwiftUI app uses a SceneDelegate with an extended UIHostingController to change the status bar style.

class MyHostingController<Content: View>: UIHostingController<Content> {
    @objc override dynamic open var preferredStatusBarStyle: UIStatusBarStyle {
        StyleManager.shared.statusBarStyle
    }
}

I noticed that in iOS 16 beta 7, the status bar style is not applied when the hosted view contains a TabView or a NavigationView with .navigationBarHidden(true).

Is this an iOS 16 bug? Or is there any way to change the status bar style manually?

struct ContentView1: View {
    var body: some View {
        TabView(selection: .constant(0)) {
            Text("Status bar style cannot be applied.")
        }
    }
}

struct ContentView2: View {
    var body: some View {
        NavigationView {
            Text("Status bar style cannot be applied.")
                .navigationTitle("title")
                .navigationBarHidden(true) // if false, status bar style can be applied.
        }
    }
}

Well you can use the .toolbarColorScheme(.dark, for: .navigationBar) now.

But only when the toolbar background is visible: .toolbarBackground(.visible, for: .navigationBar).

I still can't find a way how to set the status bar style on iOS 16 when the navigation bar is visible but has no (or transparent) background.

I independently reproduced this issue before I found this thread using the final Xcode 14.0. I found that my UIHostingViewController subclass was able to modify the status bar style by implementing the .preferredStatusBarStyle property if the hosted SwiftUI View just contained a Text, but as soon as I wrapped that Text in a NavigationView it no longer works. Checking the "Debug View Hierarchy" confirms that the whole view hierarchy changes pretty significantly just by adding the NavigationView inside of the View inside of the hosting view controller. One difference is that in my testing even setting .navigationBarHidden(false) did not restore the ability to change the status bar style. Opening the same project in Xcode 13.4.1 and running in iOS 15.5 simulator the status bar style changes as expected.

The suggestion from @taxiboatdriver is using iOS 16-only APIs so I don't think that is a solution for my app that's targeting iOS 15+. If anyone else has any solutions I'm still searching...

I also ran into the same issue, since I also need to support iOS 13 in our project, I ended up making a condition view modifier

struct ToolbarMod: ViewModifier {
  func body(content: Content) -> some View {
    if #available(iOS 16.0, *) {
      content
        .toolbarBackground(.visible, for: .navigationBar)
        .toolbarColorScheme(.light, for: .navigationBar)
    } else {
      content
    }
  }
}

That way the old behavior with preferredStatusBarStyle still works for pre iOS 16, and toolbarColorScheme is applied to iOS16. Thanks @cconway for the precision on toolbarBackground

iOS16: preferredStatusBarStyle of UIHostingController is ignored
 
 
Q