Представление контроллера дочернего представления игнорирует ограничения Auto Layout - PullRequest
0 голосов
/ 10 июля 2020

Я хотел бы добавить дочерний контроллер представления к представлению UINavigationController's. У меня есть такая иерархия NavigationController -> View (drawer) -> View (contentContainer) -> контроллер дочернего представления должен быть закреплен на contentContainer

Но по какой-то причине он игнорирует ограничения и Я получаю странные результаты. См. Снимок экрана: drawer зеленый, contentContainer желтый, а дочерний контроллер расположен почти за пределами экрана и имеет рамку с высотой 0.

enter image description here

The critical code is inside the drawerContentController didSet and setupView method. Please note that I'm using SnapKit for constraints but the same problem was happening by setting the NSLayoutConstraints traditionally

class NavigationController: UINavigationController {
    private var drawerHeightConstraint: Constraint!
    
    fileprivate lazy var drawer = UIView()
    private lazy var contentContainer = UIView()
    var drawerContentController: UIViewController? {
        didSet {
            guard let new = drawerContentController else {
                oldValue?.removeFromParent(animated: true)
                return
            }
            if let old = oldValue {
                old.removeFromParent(animated: true) { _ in
                    self.add(child: new, superview: self.contentContainer, animated: true, completion: nil)
                }
            } else {
                add(child: new, superview: contentContainer, animated: true, completion: nil)
            }
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
    }
    
    private func setupView() {
        view.addSubview(drawer)
        drawer.backgroundColor = .green
        drawer.snp.makeConstraints { make in
            make.leading.bottom.trailing.equalToSuperview()
            drawerHeightConstraint = make.height.equalTo(360).constraint
        }
        
        let blur = UIBlurEffect(style: .default)
        let visualView = UIVisualEffectView(effect: blur)
        drawer.addSubview(visualView)
        visualView.pinToSuperView()
        
        contentContainer.backgroundColor = .yellow
        drawer.addSubview(contentContainer)
        contentContainer.snp.makeConstraints { make in
            make.edges.equalTo(drawer.safeAreaLayoutGuide)
        }
    }

    func add(child controller: UIViewController, superview: UIView? = nil, animated: Bool, completion: ((Bool) -> Void)? = nil) {
        
        controller.willMove(toParent: self)
        addChild(controller)
        controller.view.alpha = 0
        (superview ?? view).addSubview(controller.view)
        controller.view.pinToSuperView()
        
        UIView.animate(withDuration: animated ? 0.3 : 0, animations: {
            controller.view.alpha = 1
        }) { finished in
            controller.didMove(toParent: self)
            completion?(finished)
        }
    }
}

extension UIView {
    func pinToSuperView() {
        snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
}

When I add a simple UIView to the contentContainer it works as expected

var drawerContentController: UIViewController? {
    didSet {
        let v = UIView()
        v.backgroundColor = .purple
        contentContainer.addSubview(v)
        v.pinToSuperView()
    }
}

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

1 Ответ

0 голосов
/ 10 июля 2020

Хорошо, я «решил» проблему.

Кажется, что UINavigationController не любит, когда к нему добавляются дочерние контроллеры представления. Как видно на скриншотах, при добавлении дочернего контроллера вся иерархия представлений навигационного контроллера нарушается. На втором снимке экрана контроллер табличного представления (белое представление) отображается правильно, но в первом случае его нет даже в иерархии представлений!

Итак, мораль такова: старайтесь не добавлять контроллеры дочерних представлений напрямую на UINavigationController, в итоге это не обычный UIViewController и даже не нормальный UIView. Я добавил еще один UIViewController в качестве контейнера для UINavigationController и добавил к нему дочерний контроллер. Теперь он работает должным образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...