Безопасная область не работает должным образом на iPhone X, если подпрограммы не находятся в области просмотра

У меня есть scrollView содержит 2 дочерних viewController. Вы можете видеть, что VC2 не правильно размещен.

Я нашел, если вид еще не виден на экране. safeAreaInsets всегда равно 0.

Я могу позвонить vc2.view.setNeedsLayout(), чтобы исправить эту проблему, когда прокрутка закончилась. Но макет неправильный, пока не закончилась прокрутка.

document говорит

Если представление в настоящее время не установлено в иерархии представлений или не является но видимый на экране, кросс-вложения этого свойства равны 0.

Итак, как я могу исправить эту ситуацию.

введите описание изображения здесь

Autolayout введите описание изображения здесь введите описание изображения здесь

Ответ 1

вместо ссылки на текущий вид safeAreaInsets, установите его в UIApplication:

(UIApplication.shared.delegate?.window??.safeAreaInsets.bottom)

Ответ 2

В ваших дочерних контроллерах вида, если вы установите контроллеры вида additionalSafeAreaInsets равными вставкам безопасной области окна, они будут правильно размещены в соответствии с безопасными областями.

Я обнаружил, что должен был сделать это внутри viewDidLoad() и viewWillTransition(to size: CGSize, with coordinator: UIVIewControllerTransitionCoordinator

Внутри viewWillTransition вы захотите установить additionalSafeAreaInsets в анимационном блоке координатора:

coordinator.animate(alongsideTransition: { _ in
    if #available(iOS 11.0, *) {
        self.additionalSafeAreaInsets = UIApplication.shared.delegate?.window??.safeAreaInsets
    }
}, completion: nil)

Ответ 3

Если я вижу, что ваш контейнерный вид прикреплен к верхней и нижней части его супервизора. Вставьте его в безопасную зону, и контроллеры вашего дочернего представления будут правильно установлены.

Ответ 4

Я создавал собственный контроллер представления подкачки и тоже столкнулся с этой проблемой @PowHU.

Единственное решение, которое мне показалось подходящим, - это установить класс представления контроллера представления в раскадровке на собственный класс, который я создал и назвал AlwaysSafeAreaInsetsView.

import UIKit

class AlwaysSafeAreaInsetsView: UIView {

    @available(iOS 11.0, *)
    override var safeAreaInsets: UIEdgeInsets {
        if let window = UIApplication.shared.keyWindow {
            return window.safeAreaInsets
        }
        return super.safeAreaInsets
    }

}