web-dev-qa-db-ja.com

UIViewのsafeAreaInsetsはiPhone Xで0

IPhone Xに対応するようにアプリを更新しています。1つを除いて、すべてのビューが正常に機能します。画面全体をカバーするカスタムUIViewを表示するView Controllerがあります。 UIScreen.main.boundsを使用してすべてのレイアウトが完了する前にビューのサイズを確認する前(collectionViewに正しいitemSizeを設定するために必要です)。 UIScreen.main.bounds.size.height - safeAreaInsets.bottomのようなことをして、適切なサイズを使用できるようになったと思いました。問題は、safeAreaInsetsがiPhone X(シミュレーター)での試行(0,0,0,0)を返すことです。何か案は?他のビューでは、safeAreaInsetsに適切な数値を取得します。

ありがとうございました!

52
Joan Cardona

私はすでに解決策を考え出しています:ビューのinitですべての実装を行っていました。 safeAreaInsetsのサイズはlayoutSubviews()で正しい

37
Joan Cardona

私は最近、viewDidLoadがトリガーされるとすぐにセーフエリアインセットが返される(0、0、0、0)という同様の問題を抱えていました。ビューの残りの部分よりも少し遅れて設定されているようです。

viewSafeAreaInsetsDidChangeをオーバーライドし、その代わりにレイアウトを実行することでそれを回避しました。

override func viewSafeAreaInsetsDidChange() {
 // ... your layout code here
} 
51

IPhone Xのキーボードに合わせてビューを上に移動しようとしても、この問題に遭遇しました。メインビューのsafeAreaInsetsは常に0です。描かれています。上記のように、私が見つけた回避策は、代わりにkeyWindowを取得し、その安全領域のインセットをチェックすることです。

Obj-C:

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

迅速:

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

その後、この値を使用して、必要に応じて制約を調整したり、フレームを表示したりできます。

23
Rory Prior

別のビュー内のサブビューであるビューがあります。 safeAreaInsetsを正しく取得できないことがわかりました。layoutSubviewsに配置しても、iPhoneXのビューでは常に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

        }

    }

}
18
Shih Ken

コンテナビューコントローラの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
  } 
}
2
BuLB JoBs

私は同じ問題に出くわしました。私の場合、view.layoutIfNeeded()を呼び出した後、挿入するビューのサイズは正しくなります。 view.safeAreaInsetsはこの後に設定されましたが、topの値のみが正しいものでした。一番下の値はまだ0(iPhone Xの場合)です。

safeAreaInsetsが正しく設定されているポイントを把握しようとしている間に、ビューのsafeAreaInsetsDidChange()メソッドにブレークポイントを追加しました。これは複数回呼び出されていましたが、バックトレースでCALayer.layoutSublayers()が表示されたときにのみ値が正しく設定されていました。

view.layoutIfNeeded()CALayerの対応するview.layer.layoutIfNeeded()に置き換えた結果、safeAreaInsetsがすぐに正しく設定され、問題が解決しました。

TL; DR

交換

view.layoutIfNeeded()

沿って

view.layer.layoutIfNeeded()
1
fphilipe
[UIApplication sharedApplication].keyWindow.safeAreaInsets return none zero
0
tounaobun

self.view.safeAreaInsetsの代わりにUIApplication.shared.keyWindow?.safeAreaInsetsを試してください。アプリケーションのkeyWindowを介して要求された場合、iOS 11.x.xデバイスではセーフエリアのインセットが塗りつぶされないようです。

0
Murat Yasar