web-dev-qa-db-ja.com

safeAreaInsetsは、viewDidLoadで誤った値を返します。それを取得するのに最適な場所はどこですか?

ビューコントローラーのviewDidLoadでsafeAreaInsetsを取得しようとすると、iPhone Xで(0、0、0、0)が返されますが、これは間違いです。ドキュメントには、ビューが階層の一部でない場合、またはビューが表示されない場合に発生することが記載されています。だから私の質問は、safeAreaInsetsを取得し、これらのインセットを使用してサブビューをレイアウトするのに最適な場所はどこですか?

15
Saoud Rizwan

viewDidLayoutSubviewsの代わりにviewDidLoadを使用する必要があります。

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

注:一度しか呼び出されないviewDidLoadとは異なり、viewDidLayoutSubviewsは複数回呼び出されることがよくあります。 viewDidLayoutSubviews内のフレームのみを設定してください。サブビューの追加など、1回だけ発生するはずの操作を実行しないでください。

17
nathangitter

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
Shih Ken