问题 safeAreaInsets在viewDidLoad中返回错误的值,哪里是获取它的最佳位置?


当我尝试在视图控制器中检索viewDidLoad中的safeAreaInsets时,它会在iPhone X上返回(0,0,0,0),我知道这是错误的。文档说如果视图不是层次结构的一部分或视图不可见,则会发生这种情况。所以我的问题是,检索safeAreaInsets然后使用这些插图布局我的子视图的最佳位置在哪里?


10434
2017-09-19 01:20


起源

您是否在代码中使用自动布局或手动布局? - nathan
@nathan我在这种情况下使用框架进行手动布局 - Saoud Rizwan


答案:


你需要使用 viewDidLayoutSubviews 代替 viewDidLoad

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // your layout code here
}

注意: 不像 viewDidLoad 只召唤一次, viewDidLayoutSubviews 通常被称为多次。确保仅在内部设置框架 viewDidLayoutSubviews,并且不执行仅应该发生一次的操作,例如添加子视图。


13
2017-09-19 01:26



这是一个好主意,但不幸的是,在我的情况下,它会在使用不正确的safeAreaInsets进行轮换期间调用,这会导致我出现问题。对于大多数人来说,它可能无关紧要,但只是让其他人看到这个...它有时被称为奇怪的插图(可能在动画期间)。 - Oded
@Oded但是你得到了 viewWillLayoutSubviews  和 viewDidLayoutSubviews 叫做 多 轮换期间? - Yevhen Dubinin
@nathan我想你可以用 viewWillLayoutSubviews 代替 viewDidLayoutSubviews。 - Ehtesham Hasan
@YevhenDubinin自从我使用该代码已经有几周了,但我想我做到了。 - Oded
@Oded无论如何,@ nathan提出的解决方案应该可行。你可以看看我的博文: “在将UI改编为iPhone X时远离设备模型”,哪里 viewDidLayoutSubviews 也用了。 - Yevhen Dubinin


我有一个自定义视图,它是滚动视图的内容视图,使用drawrect绘制UI。 内容视图是根据其大小绘制的,因此我需要在drawrect函数中获得安全区域宽度。 事实证明,我无法正确获得safeAreaInsets,即使我把它放在layoutsubviews中也总是返回零。 我终于找到答案是我可以通过UIApplication.shared.keyWindow成功获得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

        }

    }

}

0
2017-12-16 04:37