update for 13.4
note: revisiting this the next day, it may be possible that some of my issues were caused by my somewhat nonstandard setup: i am still running mojave, but have manually added the 13.4 support files (normally available only via xcode 11.4, which requires catalina). i mention this because i am/was also having some tab bar custom color issues, but i just noticed that those are only manifesting when i have the phone actually plugged in and am running the app from xcode. if i unplug, and just run the app normally, i am not seeing the tab bar issues, so it may be possible that the nav bar issue had some similarity ...
(i would add this as a comment on arsenius' answer (the currently accepted one) above, but i don't have the rep, so ...)
i was using that solution, and it was working perfectly up until 13.4, which seems to have broken it, at least for me. after a lot of view hierarchy tracing, it looks like they changed things such that the implicit UINavigationController is no longer easily accessible via the passed UIViewController as described in the workaround. it's still there though (pretty far up the tree), we just have to find it.
to that end, we can just walk the view hierarchy until we find the navbar, and then set the desired parameters on it, as usual. this necessitates a new discovery function, and some minor changes to the NavigationConfigurator struct, and its instantiation ...
first up, the discovery function:
func find_navbar(_ root: UIView?) -> UINavigationBar?
{
guard root != nil else { return nil }
var navbar: UINavigationBar? = nil
for v in root!.subviews
{ if type(of: v) == UINavigationBar.self { navbar = (v as! UINavigationBar); break }
else { navbar = find_navbar(v); if navbar != nil { break } }
}
return navbar
}
modify the NavigationConfigurator as follows (note that we no longer care about passing in a view, since that's no longer reliable):
struct NavigationConfigurator: UIViewControllerRepresentable
{
@EnvironmentObject var prefs: Prefs // to pick up colorscheme changes
var configure: () -> Void = {}
func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController { UIViewController() }
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) { self.configure() }
}
(in my app, i have a Prefs object which keeps track of colors, etc.)
... then, at the instantiation site, do something like this:
MyView()
.navigationBarTitle("List", displayMode: .inline)
.navigationBarItems(trailing: navbuttons)
.background(NavigationConfigurator {
if self.prefs.UI_COLORSCHEME != Colorscheme.system.rawValue
{ if let navbar = find_navbar(root_vc?.view)
{ navbar.barTintColor = Colors.uicolor(.navbar, .background)
navbar.backgroundColor = .black
navbar.titleTextAttributes = [.foregroundColor: Colors.uicolor(.navbar, .foreground)]
navbar.tintColor = Colors.uicolor(.navbar, .foreground)
}
}
})
note that i capture the root view controller elsewhere in my app, and use it here to pass to find_navbar(). you might want to do it differently, but i already have that variable around for other reasons ... there's some other stuff there specific to my app, e.g., the color-related objects, but you get the idea.