子视图控制器的视图忽略“自动布局”约束

时间:2020-07-10 17:42:18

标签: ios swift autolayout

我想将子视图控制器添加到UINavigationController's视图中。我有这样的等级 NavigationController-> View(drawer)-> View(contentContainer)->子视图控制器应固定到contentContainer

但是由于某种原因,它忽略了约束,所以我得到了奇怪的结果。请查看屏幕截图,drawer为绿色,contentContainer为黄色,并且子控制器几乎位于屏幕外部,并且框架的高度为0。

enter image description here

关键代码位于drawerContentController didSetsetupView方法中。请注意,我使用SnapKit进行约束,但是通过传统地设置NSLayoutConstraints

也会发生相同的问题
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()
        }
    }
}

当我将一个简单的UIView添加到contentContainer时,它会按预期工作

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

enter image description here

1 个答案:

答案 0 :(得分:-1)

好的,我“解决了”问题。

似乎UINavigationController不喜欢添加子视图控制器。如屏幕截图所示,添加子控制器后,导航控制器的整个视图层次结构都被破坏了。在第二张屏幕截图中,表视图控制器(白色视图)正确显示,但在第一种情况下,它甚至不在视图层次结构中!

因此,应避免将子视图控制器不直接添加到UINavigationController中,最后这不是正常的UIViewController,甚至没有正常的UIView。我添加了另一个UIViewController作为UINavigationController的容器,并向其添加了子控制器。现在可以正常工作了。