ios-在iPhone X上UIView中的safeAreaInsets为0

我正在更新我的应用程序以使其适合iPhoneX。除一个视图外,所有视图现在都可以正常工作。 我有一个视图控制器,它提供了一个覆盖整个屏幕的自定义UIView。 在我使用UIScreen.main.bounds来确定所有布局之前的视图大小之前(我需要使用它来为collectionView放置正确的itemSize)。 我以为现在我可以做些类似的事情  UIScreen.main.bounds.size.height - safeAreaInsets.bottom获得正确的可用大小。 问题是,在iPhone X(模拟器)上尝试使用safeAreaInsets会返回(0,0,0,0)。 有任何想法吗? 在其他视图中,我获得了safeAreaInsets的正确数字。

谢谢!

Joan Cardona asked 2019-11-18T06:59:23Z
8个解决方案
57 votes

最近,我遇到了类似的问题,即一旦触发viewDidLoad,安全区域插图就会返回(0,0,0,0)。 似乎它们的设置比视图加载的其余部分晚。

我通过重写viewSafeAreaInsetsDidChange并在其中进行布局来解决这个问题:

override func viewSafeAreaInsetsDidChange() {
 // ... your layout code here
} 
Richard West-Soley answered 2019-11-18T07:00:02Z
37 votes

我已经找到了解决方案:我正在视图的init中进行所有实现。 safeAreaInsets在layoutSubviews()中具有正确的大小

Joan Cardona answered 2019-11-18T07:00:28Z
25 votes

我也遇到过这个问题,试图向上移动视图以为iPhone X上的键盘腾出空间。主视图的safeAreaInsets始终为0,即使我知道此时子视图已经作为屏幕布置了 已被绘制。 如上所述,我发现的一种解决方法是获取keyWindow并检查其安全区域插图。

对象C:

CGFloat bottomInset = [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom;

迅速:

let bottomInset = UIApplication.shared.keyWindow?.safeAreaInsets.bottom

然后,您可以根据需要使用此值来调整约束或查看框架。

Rory Prior answered 2019-11-18T07:01:08Z
18 votes

我有一个视图,它是另一个视图内的子视图。我发现我无法正确获取safeAreaInsets,即使在iPhoneX上的该视图中,即使将它放在layoutSubviews中,它也始终返回0。最终的解决方案是我使用以下UIScreen扩展来检测safeAreaInsets,它们可以像超级按钮一样工作。

extension UIScreen {

    func widthOfSafeArea() -> CGFloat {

        guard let rootView = UIApplication.shared.keyWindow else { return 0 }

        if #available(iOS 11.0, *) {

            let leftInset = rootView.safeAreaInsets.left

            let rightInset = rootView.safeAreaInsets.right

            return rootView.bounds.width - leftInset - rightInset

        } else {

            return rootView.bounds.width

        }

    }

    func heightOfSafeArea() -> CGFloat {

        guard let rootView = UIApplication.shared.keyWindow else { return 0 }

        if #available(iOS 11.0, *) {

            let topInset = rootView.safeAreaInsets.top

            let bottomInset = rootView.safeAreaInsets.bottom

            return rootView.bounds.height - topInset - bottomInset

        } else {

            return rootView.bounds.height

        }

    }

}
Shih Ken answered 2019-11-18T07:01:35Z
2 votes

容器视图控制器的viewDidAppear(_ :)方法,该方法扩展了其嵌入式子视图控制器的安全区域,以解决中的视图。

在此方法中进行修改,因为在将视图添加到视图层次结构之前,该视图的安全区域插图不准确。

override func viewDidAppear(_ animated: Bool) {

   if (@available(iOS 11, *)) {

     var newSafeArea = view.safeAreaInsets

     // Adjust the safe area to accommodate 
     //  the width of the side view.

     if let sideViewWidth = sideView?.bounds.size.width {
        newSafeArea.right += sideViewWidth
     }

    // Adjust the safe area to accommodate 
    //  the height of the bottom view.
    if let bottomViewHeight = bottomView?.bounds.size.height {
       newSafeArea.bottom += bottomViewHeight
    }

    // Adjust the safe area insets of the 
    //  embedded child view controller.
    let child = self.childViewControllers[0]
    child.additionalSafeAreaInsets = newSafeArea
  } 
}
BuLB JoBs answered 2019-11-18T07:02:11Z
1 votes

我遇到了同样的问题。 就我而言,我要插入的视图在调用view.layoutIfNeeded()后将正确调整大小。此后设置了CALayer,但是只有view.layer.layoutIfNeeded()值正确。 最低值仍然是safeAreaInsets(在iPhone X上为最低)。

在尝试弄清楚view.layoutIfNeeded()的正确设置点时,我在视图的CALayer方法上添加了一个断点。 这被多次调用,但是仅当我在回溯中看到view.layer.layoutIfNeeded()时,才正确设置了该值。

因此,我将view.layoutIfNeeded()替换为CALayer的对应产品2619306726402819819074,这导致立即正确设置safeAreaInsets,从而解决了我的问题。

TL; DR

更换

view.layoutIfNeeded()

通过

view.layer.layoutIfNeeded()
fphilipe answered 2019-11-18T07:02:58Z
0 votes
[UIApplication sharedApplication].keyWindow.safeAreaInsets return none zero
tounaobun answered 2019-11-18T07:03:18Z
0 votes

只需尝试self.view.safeAreaInsets而不是UIApplication.shared.keyWindow?.safeAreaInsets通过应用程序keyWindow请求时,安全区域插图似乎无法在iOS 11.x.x设备上填充。

Murat Yasar answered 2019-11-18T07:03:46Z
translate from https://stackoverflow.com:/questions/47032855/safeareainsets-in-uiview-is-0-on-an-iphone-x