I'm trying to add a view to my app that is persistent across flows and sits above all other views. In previous versions of iOS i've been able to simply add a subview to the UIWindow
that sat atop my application however it would appear that as of iOS 13 this is no longer possible.
I've tried the following, but to no success:
UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.addSubview(someView)
Debugging a bit further, it appears that my app does not have a window at all present on its view hierarchy. I know this because when putting a breakpoint on the follow forEach statement, I never get a breakpoint to execute.
UIApplication.shared.windows.forEach { (window) in
window.addSubview(myView)
}
Any advice on how to achieve this, on all iOS versions 11 through 14 would be much appreciated.
You have to create a second UIWindow
, assign the rootViewController
and make it visible.
The code bellow is for SwiftUI, but you can do the same with UIKit, just create a window and set window.isHidden = false
.
let secondWindow = UIWindow(windowScene: windowScene)
secondWindow.frame = CGRect(x: 0, y: 40, width: UIScreen.main.bounds.size.width, height: 100)
let someView = Text("I am on top of everything")
secondWindow.rootViewController = UIHostingController(rootView: someView)
secondWindow.isHidden = false
Depending on how many windows you have. You might need to change the windowLevel
of your second window.
You can check if the window is displayed using Debug View Hierarchy
from Xcode.
This is a UIKit example without SceneDelegate. If you have scene delegate you have to pass the window scene to the UIWindow init. Don't forget to retain the second window.
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
private enum Constants {
static let sessionConfiguration = URLSessionConfiguration.default
}
var window: UIWindow?
var secondWindow: UIWindow?
// MARK: - UIApplicationDelegate
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
self.window = window
let viewController = UIViewController()
viewController.view.backgroundColor = .red
window.rootViewController = viewController
window.makeKeyAndVisible()
let secondWindow = UIWindow()
secondWindow.frame = CGRect(
x: 0,
y: 40,
width: UIScreen.main.bounds.size.width,
height: 100
)
let secondController = UIViewController()
secondController.view.backgroundColor = .blue
secondWindow.rootViewController = secondController
secondWindow.isHidden = false
self.secondWindow = secondWindow
return true
}
}