iOS13中如何获取状态栏高度?
How to get the status bar height in iOS 13?
在iOS 13 UIApplication.shared.statusBarFrame.height
警告
'statusBarFrame' was deprecated in iOS 13.0: Use the statusBarManager
property of the window scene instead.
如何在不使用 iOS 13 中已弃用的 API 的情况下获得状态栏高度?
如警告提示,您可以访问 statusBarManager
,其中有一个 statusBarFrame
属性。这是在您的 UIWindow
的 windowScene
.
上定义的
let height = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
试试,我试过了
let window = UIApplication.shared.windows.filter {[=10=].isKeyWindow}.first
let height = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
我遇到了与 MMV 相同的问题(请参阅他们对 Jordan H 的回答的评论),view.window?.windowScene?.statusBarManager?.statusBarFrame.height
在我的应用程序启动时返回 nil。具体来说 view.window
返回 nil。然后我尝试在 UIApplication.shared:
上搜索 windows 属性
for window in UIApplication.shared.windows
在我的例子中,这返回了两个 windows。两个 windows 都有相等的非零状态栏高度。我不确定为什么会有两个 windows,但至少两者的状态栏高度相同。我像这样访问状态栏高度:
if let height = window.windowScene?.statusBarManager?.statusBarFrame.height
我决定在我的例子中,因为可能有不同的高度来为我的代码取最大的高度。这是我用于我的应用程序的代码:
let statusBarHeight: CGFloat = {
var heightToReturn: CGFloat = 0.0
for window in UIApplication.shared.windows {
if let height = window.windowScene?.statusBarManager?.statusBarFrame.height, height > heightToReturn {
heightToReturn = height
}
}
return heightToReturn
}()
希望这对某人有所帮助!
var statusBarHeight: CGFloat = 0
if #available(iOS 13.0, *) {
statusBarHeight = UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
} else {
statusBarHeight = UIApplication.shared.statusBarFrame.height
}
解法:
这似乎在 iPhoneX+ 设备中也没有任何警告。
Swift 4.2 / 5
if #available(iOS 13.0, *) {
let window = UIApplication.shared.windows.filter {[=10=].isKeyWindow}.first
statusBarHeight = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
} else {
statusBarHeight = UIApplication.shared.statusBarFrame.height
}
试试吧。希望对你有帮助。
对于 iOS 13:
在你的 SceneDelegate
:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let statusBarSize = windowScene.statusBarManager!.statusBarFrame
...// initialize your root view controller
}
}
如果您想将值传递给您的 View
,您可以将值设置为 Environment
并在您的 View
中使用它。示例:
首先我们需要创建我们的环境密钥:
struct StatusBarSizeEnvironmentKey: EnvironmentKey {
public static let defaultValue: CGRect = CGRect()
}
extension EnvironmentValues {
public var statusBarSize: CGRect {
set { self[StatusBarSizeEnvironmentKey.self] = newValue }
get { self[StatusBarSizeEnvironmentKey] }
}
}
并在SceneDelegate
中设置值:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let statusBarSize = windowScene.statusBarManager!.statusBarFrame
window.rootViewController = UIHostingController(rootView: YourView()
.environment(\.statusBarSize, statusBarSize))
}
}
从这里已经给出的很好的答案中学习,使用 UIApplication
中的 connectScenes
,我们可以进行扩展:
extension UIApplication {
var statusBarHeight: CGFloat {
connectedScenes
.compactMap {
[=10=] as? UIWindowScene
}
.compactMap {
[=10=].statusBarManager
}
.map {
[=10=].statusBarFrame
}
.map(\.height)
.max() ?? 0
}
}
用法:
let height = UIApplication.shared.statusBarHeight
最新获取statusBarHeight的方法如下:
private lazy var statusBarHeight: CGFloat = {
var statusBarHeight: CGFloat = 0
if #available(iOS 13.0, *) {
let window = UIApplication.shared.windows.filter {[=10=].isKeyWindow}.first
statusBarHeight = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
} else {
statusBarHeight = UIApplication.shared.statusBarFrame.height
}
return statusBarHeight
}()
从已接受的答案中窃取:
guard let sbheight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height else {
assertionFailure("usage error: VC lifecyclewise it becomes available no earlier than viewDidAppear")
}
对于Objective-C
我不确定 OC 中过滤器的替代方法是什么,所以我使用 for 循环来获取 keyWindow
。好吧,我在 iPhone 12 中得到的实际高度是“47”,在 iPhone 8 中得到的实际高度是“20”。
CGFloat statusBarHeight;
if (@available(iOS 13, *)) {
NSArray *windows = UIApplication.sharedApplication.windows;
UIWindow *keyWindow = nil;
for (UIWindow *window in windows) {
if (window.isKeyWindow) {
keyWindow = window;
break;
}
}
statusBarHeight = keyWindow.windowScene.statusBarManager.statusBarFrame.size.height;
NSLog(@"statusBarHeight: %f", statusBarHeight);
} else {
statusBarHeight = UIApplication.sharedApplication.statusBarFrame.size.height;
}
UIApplication.shared.windowswindows 在 iOS 15.0
中被弃用
iOS 15
let statusBarHeight = UIApplication.shared.connectedScenes
.filter {[=10=].activationState == .foregroundActive }
.map {[=10=] as? UIWindowScene }
.compactMap { [=10=] }
.first?.windows
.filter({ [=10=].isKeyWindow }).first?
.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
对于Objective-C
- (CGFloat)statusBarHeight{
UIWindowScene * scene = nil;
for (UIWindowScene* wScene in [UIApplication sharedApplication].connectedScenes){
if (wScene.activationState == UISceneActivationStateForegroundActive){
scene = wScene;
break;
}
}
return scene.statusBarManager.statusBarFrame.size.height;
}
我觉得上面的也OK,@ChuckZHB的回答
在iOS 13 UIApplication.shared.statusBarFrame.height
警告
'statusBarFrame' was deprecated in iOS 13.0: Use the statusBarManager property of the window scene instead.
如何在不使用 iOS 13 中已弃用的 API 的情况下获得状态栏高度?
如警告提示,您可以访问 statusBarManager
,其中有一个 statusBarFrame
属性。这是在您的 UIWindow
的 windowScene
.
let height = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
试试,我试过了
let window = UIApplication.shared.windows.filter {[=10=].isKeyWindow}.first
let height = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
我遇到了与 MMV 相同的问题(请参阅他们对 Jordan H 的回答的评论),view.window?.windowScene?.statusBarManager?.statusBarFrame.height
在我的应用程序启动时返回 nil。具体来说 view.window
返回 nil。然后我尝试在 UIApplication.shared:
for window in UIApplication.shared.windows
在我的例子中,这返回了两个 windows。两个 windows 都有相等的非零状态栏高度。我不确定为什么会有两个 windows,但至少两者的状态栏高度相同。我像这样访问状态栏高度:
if let height = window.windowScene?.statusBarManager?.statusBarFrame.height
我决定在我的例子中,因为可能有不同的高度来为我的代码取最大的高度。这是我用于我的应用程序的代码:
let statusBarHeight: CGFloat = {
var heightToReturn: CGFloat = 0.0
for window in UIApplication.shared.windows {
if let height = window.windowScene?.statusBarManager?.statusBarFrame.height, height > heightToReturn {
heightToReturn = height
}
}
return heightToReturn
}()
希望这对某人有所帮助!
var statusBarHeight: CGFloat = 0
if #available(iOS 13.0, *) {
statusBarHeight = UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
} else {
statusBarHeight = UIApplication.shared.statusBarFrame.height
}
解法:
这似乎在 iPhoneX+ 设备中也没有任何警告。
Swift 4.2 / 5
if #available(iOS 13.0, *) {
let window = UIApplication.shared.windows.filter {[=10=].isKeyWindow}.first
statusBarHeight = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
} else {
statusBarHeight = UIApplication.shared.statusBarFrame.height
}
试试吧。希望对你有帮助。
对于 iOS 13:
在你的 SceneDelegate
:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let statusBarSize = windowScene.statusBarManager!.statusBarFrame
...// initialize your root view controller
}
}
如果您想将值传递给您的 View
,您可以将值设置为 Environment
并在您的 View
中使用它。示例:
首先我们需要创建我们的环境密钥:
struct StatusBarSizeEnvironmentKey: EnvironmentKey {
public static let defaultValue: CGRect = CGRect()
}
extension EnvironmentValues {
public var statusBarSize: CGRect {
set { self[StatusBarSizeEnvironmentKey.self] = newValue }
get { self[StatusBarSizeEnvironmentKey] }
}
}
并在SceneDelegate
中设置值:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let statusBarSize = windowScene.statusBarManager!.statusBarFrame
window.rootViewController = UIHostingController(rootView: YourView()
.environment(\.statusBarSize, statusBarSize))
}
}
从这里已经给出的很好的答案中学习,使用 UIApplication
中的 connectScenes
,我们可以进行扩展:
extension UIApplication {
var statusBarHeight: CGFloat {
connectedScenes
.compactMap {
[=10=] as? UIWindowScene
}
.compactMap {
[=10=].statusBarManager
}
.map {
[=10=].statusBarFrame
}
.map(\.height)
.max() ?? 0
}
}
用法:
let height = UIApplication.shared.statusBarHeight
最新获取statusBarHeight的方法如下:
private lazy var statusBarHeight: CGFloat = {
var statusBarHeight: CGFloat = 0
if #available(iOS 13.0, *) {
let window = UIApplication.shared.windows.filter {[=10=].isKeyWindow}.first
statusBarHeight = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
} else {
statusBarHeight = UIApplication.shared.statusBarFrame.height
}
return statusBarHeight
}()
从已接受的答案中窃取:
guard let sbheight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height else {
assertionFailure("usage error: VC lifecyclewise it becomes available no earlier than viewDidAppear")
}
对于Objective-C
我不确定 OC 中过滤器的替代方法是什么,所以我使用 for 循环来获取 keyWindow
。好吧,我在 iPhone 12 中得到的实际高度是“47”,在 iPhone 8 中得到的实际高度是“20”。
CGFloat statusBarHeight;
if (@available(iOS 13, *)) {
NSArray *windows = UIApplication.sharedApplication.windows;
UIWindow *keyWindow = nil;
for (UIWindow *window in windows) {
if (window.isKeyWindow) {
keyWindow = window;
break;
}
}
statusBarHeight = keyWindow.windowScene.statusBarManager.statusBarFrame.size.height;
NSLog(@"statusBarHeight: %f", statusBarHeight);
} else {
statusBarHeight = UIApplication.sharedApplication.statusBarFrame.size.height;
}
UIApplication.shared.windowswindows 在 iOS 15.0
中被弃用iOS 15
let statusBarHeight = UIApplication.shared.connectedScenes
.filter {[=10=].activationState == .foregroundActive }
.map {[=10=] as? UIWindowScene }
.compactMap { [=10=] }
.first?.windows
.filter({ [=10=].isKeyWindow }).first?
.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
对于Objective-C
- (CGFloat)statusBarHeight{
UIWindowScene * scene = nil;
for (UIWindowScene* wScene in [UIApplication sharedApplication].connectedScenes){
if (wScene.activationState == UISceneActivationStateForegroundActive){
scene = wScene;
break;
}
}
return scene.statusBarManager.statusBarFrame.size.height;
}
我觉得上面的也OK,@ChuckZHB的回答