如何在 iOS 13/14 中将视图添加到应用程序的顶部
How do I add a view to the top of an app in iOS 13/14
我正在尝试向我的应用程序添加一个视图,该视图在流中持久存在并且位于所有其他视图之上。在以前的 iOS 版本中,我已经能够简单地向位于我的应用程序顶部的 UIWindow
添加一个子视图,但是从 iOS 13 开始,这似乎不再可能。
我尝试了以下方法,但没有成功:
UIApplication.shared.windows.first(where: { [=13=].isKeyWindow })?.addSubview(someView)
进一步调试,我的应用程序的视图层次结构中似乎根本没有 window。我知道这是因为在 follow forEach 语句上放置断点时,我从来没有得到要执行的断点。
UIApplication.shared.windows.forEach { (window) in
window.addSubview(myView)
}
对于如何在所有 iOS 版本 11 到 14 上实现这一点的任何建议,我们将不胜感激。
您必须创建第二个 UIWindow
,分配 rootViewController
并使其可见。
下面的代码是针对 SwiftUI 的,但是你可以用 UIKit 做同样的事情,只需创建一个 window 并设置 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
取决于你有多少windows。您可能需要更改第二个 window 的 windowLevel
。
您可以使用 Xcode 中的 Debug View Hierarchy
检查 window 是否显示。
这是一个没有 SceneDelegate 的 UIKit 示例。如果您有场景委托,则必须将 window 场景传递给 UIWindow init。
不要忘记保留第二个 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
}
}
我正在尝试向我的应用程序添加一个视图,该视图在流中持久存在并且位于所有其他视图之上。在以前的 iOS 版本中,我已经能够简单地向位于我的应用程序顶部的 UIWindow
添加一个子视图,但是从 iOS 13 开始,这似乎不再可能。
我尝试了以下方法,但没有成功:
UIApplication.shared.windows.first(where: { [=13=].isKeyWindow })?.addSubview(someView)
进一步调试,我的应用程序的视图层次结构中似乎根本没有 window。我知道这是因为在 follow forEach 语句上放置断点时,我从来没有得到要执行的断点。
UIApplication.shared.windows.forEach { (window) in
window.addSubview(myView)
}
对于如何在所有 iOS 版本 11 到 14 上实现这一点的任何建议,我们将不胜感激。
您必须创建第二个 UIWindow
,分配 rootViewController
并使其可见。
下面的代码是针对 SwiftUI 的,但是你可以用 UIKit 做同样的事情,只需创建一个 window 并设置 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
取决于你有多少windows。您可能需要更改第二个 window 的 windowLevel
。
您可以使用 Xcode 中的 Debug View Hierarchy
检查 window 是否显示。
这是一个没有 SceneDelegate 的 UIKit 示例。如果您有场景委托,则必须将 window 场景传递给 UIWindow init。 不要忘记保留第二个 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
}
}