最合适的方法是什么来获得不安全区域的顶部和底部高度?


当前回答

Swift 5, Xcode 11.4

`UIApplication.shared.keyWindow` 

它将给出弃用警告。" keyWindow "在iOS 13.0中已弃用:不应该用于支持多场景的应用程序,因为它会在所有连接的场景中返回一个键窗口。我用这种方法。

extension UIView {

    var safeAreaBottom: CGFloat {
         if #available(iOS 11, *) {
            if let window = UIApplication.shared.keyWindowInConnectedScenes {
                return window.safeAreaInsets.bottom
            }
         }
         return 0
    }

    var safeAreaTop: CGFloat {
         if #available(iOS 11, *) {
            if let window = UIApplication.shared.keyWindowInConnectedScenes {
                return window.safeAreaInsets.top
            }
         }
         return 0
    }
}

extension UIApplication {
    var keyWindowInConnectedScenes: UIWindow? {
        return windows.first(where: { $0.isKeyWindow })
    }
}

其他回答

要获得布局参考线之间的高度,只需这样做

let guide = view.safeAreaLayoutGuide
let height = guide.layoutFrame.size.height

所以全帧高度= 812.0,安全区高度= 734.0

下面的例子中,绿色视图的框架为guide.layoutFrame

objective - c 当keyWindow等于nil时谁有问题。 把上面的代码放在viewDidAppear中(不是viewDidLoad中)

extension UIViewController {
    var topbarHeight: CGFloat {
        return
            (view.window?.safeAreaInsets.top ?? 0) +
            (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

Swift 5, Xcode 11.4

`UIApplication.shared.keyWindow` 

它将给出弃用警告。" keyWindow "在iOS 13.0中已弃用:不应该用于支持多场景的应用程序,因为它会在所有连接的场景中返回一个键窗口。我用这种方法。

extension UIView {

    var safeAreaBottom: CGFloat {
         if #available(iOS 11, *) {
            if let window = UIApplication.shared.keyWindowInConnectedScenes {
                return window.safeAreaInsets.bottom
            }
         }
         return 0
    }

    var safeAreaTop: CGFloat {
         if #available(iOS 11, *) {
            if let window = UIApplication.shared.keyWindowInConnectedScenes {
                return window.safeAreaInsets.top
            }
         }
         return 0
    }
}

extension UIApplication {
    var keyWindowInConnectedScenes: UIWindow? {
        return windows.first(where: { $0.isKeyWindow })
    }
}

这里有一个基于其他答案的免费函数,当你的rootController从任何地方布局时,它都应该是可调用的。你可以把它当做一个独立的函数。

    func safeAreaInsets() -> UIEdgeInsets? {
    (UIApplication
        .shared
        .keyWindow?
        .rootViewController)
        .flatMap {
            if #available(iOS 11.0, *) {
                return $0.view.safeAreaInsets
            } else {
                return .init(
                    top: $0.topLayoutGuide.length,
                    left: .zero,
                    bottom: $0.bottomLayoutGuide.length,
                    right: .zero
                )
            }
        }
}