Issue #908
When we add another UIWindow
, then its rootViewController will decide the style of the status bar, not the rootViewController of the keyWindow
anymore
childForStatusBarStyle
The usual way to fix this is to defer the decision to the correct rootViewController
, like in our HUDViewController
class HUDViewController: UIViewController {
override var childForStatusBarStyle: UIViewController? {
let windows = view.window?.windowScene?.windows ?? []
for window in windows where window != self.view.window {
return window.rootViewController?.childForStatusBarStyle
}
return nil
}
}
This works, but in case we present some view controllers, the status bar now lays on a dark content. And we don’t know when to call setNeedsStatusBarAppearanceUpdate
for childForStatusBarStyle
to kick in again
Overriding rootViewController
A workaround is to override rootViewController
to return the keyWindow
rootViewController
instead
final class HUDWindow: UIWindow {
override public var rootViewController: UIViewController? {
get {
for window in windowScene?.windows where self != window {
if let rootViewController = window.rootViewController {
return rootViewController
}
}
return super.rootViewController
}
set {
super.rootViewController = newValue
}
}
}
This comes with another problem: our HUDWindow now propagates the safeAreaInsets
to the keyWindow
rootViewController
instead of its own rootViewController
, resulting in wrong area insets for the HUD content.
One way to fix this is to listen to safeAreaInsetsDidChange
. I found out that by altering additionalSafeAreaInsets
, the view controller somehow invalidates its safeAreaInsets
class HUDWindow: UIWindow {
public override func safeAreaInsetsDidChange() {
super.rootViewController?.additionalSafeAreaInsets = safeAreaInsets
DispatchQueue.main.async {
super.rootViewController?.additionalSafeAreaInsets = .zero
}
}
}
Another way is to reach to safeAreaInsets
from the window instead. For example from HUDViewController
SwiftUIView()
.ignoresSafeArea(.all, edges: .all)
.padding(view.window?.safeAreaInsets)
modalPresentationCapturesStatusBarAppearance
modalPresentationCapturesStatusBarAppearance
Specifies whether a view controller, presented non-fullscreen, takes over control of status bar appearance from the presenting view controller.
We can set modalPresentationCapturesStatusBarAppearance
to false
to prevent the hud view controller from taking over the status bar style decision
hudViewController.modalPresentationCapturesStatusBarAppearance = false