首页 > 解决方案 > 不明确的布局(以编程方式添加的约束)

问题描述

我不知道为什么我以编程方式创建的约束是模棱两可的。我的应用程序在 stackview 中有两个容器视图。其中一个容器视图kanjiView充当导航栏下方的下拉窗口。有人可以指出我正确的方向吗?

override func viewDidLoad() {
    super.viewDidLoad()

    // Add Kanji View Container
    let kanjiView = UIView()
    view.addSubview(kanjiView)

    // add child view controller view to container
    let kanjiController = storyboard!.instantiateViewController(withIdentifier: "KanjiDictionaryTab")
    addChild(kanjiController)
    kanjiView.addSubview(kanjiController.view)
    kanjiController.didMove(toParent: self)
    
    // Add Safari View Container
    let safariView = UIView()
    view.addSubview(safariView)

    // add child view controller view to container
    let safariController = storyboard!.instantiateViewController(withIdentifier: "SafariTab")
    addChild(safariController)
    safariView.addSubview(safariController.view)
    safariController.didMove(toParent: self)
    
    //Create StackView
    let stackView = UIStackView()
    stackView.spacing = 0
    stackView.axis = .vertical
    stackView.distribution = .equalSpacing
    stackView.alignment = .center
    
    stackView.addArrangedSubview(kanjiView)
    stackView.addArrangedSubview(safariView)
    view.addSubview(stackView)
    
    //Disable Autoresize
    kanjiView.translatesAutoresizingMaskIntoConstraints = false
    kanjiController.view.translatesAutoresizingMaskIntoConstraints = false
    safariView.translatesAutoresizingMaskIntoConstraints = false
    safariController.view.translatesAutoresizingMaskIntoConstraints = false
    stackView.translatesAutoresizingMaskIntoConstraints = false
    //self.view.translatesAutoresizingMaskIntoConstraints = false
    
    //Add Constraints
    NSLayoutConstraint.activate([
        kanjiController.view.leadingAnchor.constraint(equalTo: kanjiView.leadingAnchor),
        kanjiController.view.trailingAnchor.constraint(equalTo: kanjiView.trailingAnchor),
        kanjiController.view.topAnchor.constraint(equalTo: kanjiView.topAnchor),
        kanjiController.view.bottomAnchor.constraint(equalTo: kanjiView.bottomAnchor),
        
        safariView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
        safariView.heightAnchor.constraint(equalToConstant: self.view.frame.height*3/4),
        kanjiView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
        kanjiView.heightAnchor.constraint(equalToConstant: self.view.frame.height*1/4),
        //kanjiView.heightAnchor.constraint(lessThanOrEqualToConstant: self.view.frame.height*1/4),
        
        safariController.view.leadingAnchor.constraint(equalTo: safariView.leadingAnchor),
        safariController.view.trailingAnchor.constraint(equalTo: safariView.trailingAnchor),
        safariController.view.topAnchor.constraint(equalTo: safariView.topAnchor),
        safariController.view.bottomAnchor.constraint(equalTo: safariView.bottomAnchor),
        
        //stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
        //stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
        stackView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
        stackView.heightAnchor.constraint(equalToConstant: self.view.frame.height),
       
        
        NSLayoutConstraint(item: stackView, attribute: .top, relatedBy: .equal, toItem: view.layoutMarginsGuide, attribute: .top, multiplier: 1.0, constant: 0),
        NSLayoutConstraint(item: stackView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0),
        NSLayoutConstraint(item: stackView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0),
        NSLayoutConstraint(item: stackView, attribute: .bottom, relatedBy: .equal, toItem: view.layoutMarginsGuide, attribute: .bottom, multiplier: 1, constant: 0),
    ])
}

这是用于隐藏的功能kanjiView

func hideKanji() {
    UIView.animate(withDuration: 0.35) {
        self.kanjiView.isHidden.toggle()
        self.stackView.layoutIfNeeded()
    }
}

这是控制台中的输出警告:

(
    "<NSLayoutConstraint:0x6000021649b0 UIStackView:0x7ff2d6c12980.height == 844   (active)>",
    "<NSLayoutConstraint:0x600002164cd0 UIStackView:0x7ff2d6c12980.top == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.top   (active)>",
    "<NSLayoutConstraint:0x600002164dc0 UIStackView:0x7ff2d6c12980.bottom == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.bottom   (active)>",
    "<NSLayoutConstraint:0x600002164aa0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide']-(83)-|   (active, names: '|':UIView:0x7ff2f6d1d990 )>",
    "<NSLayoutConstraint:0x600002153480 'UIView-Encapsulated-Layout-Height' UIView:0x7ff2f6d1d990.height == 844   (active)>",
    "<NSLayoutConstraint:0x600002164a00 'UIView-topMargin-guide-constraint' V:|-(91)-[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide']   (active, names: '|':UIView:0x7ff2f6d1d990 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x6000021649b0 UIStackView:0x7ff2d6c12980.height == 844   (active)>

(
    "<NSLayoutConstraint:0x600002164730 UIView:0x7ff2d6c12810.height == 633   (active)>",
    "<NSLayoutConstraint:0x6000021647d0 UIView:0x7ff2d6c116e0.height == 211   (active)>",
    "<NSLayoutConstraint:0x600002164cd0 UIStackView:0x7ff2d6c12980.top == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.top   (active)>",
    "<NSLayoutConstraint:0x600002164dc0 UIStackView:0x7ff2d6c12980.bottom == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.bottom   (active)>",
    "<NSLayoutConstraint:0x600002151fe0 'UISV-canvas-connection' UIStackView:0x7ff2d6c12980.top == UIView:0x7ff2d6c116e0.top   (active)>",
    "<NSLayoutConstraint:0x6000021533e0 'UISV-canvas-connection' V:[UIView:0x7ff2d6c12810]-(0)-|   (active, names: '|':UIStackView:0x7ff2d6c12980 )>",
    "<NSLayoutConstraint:0x600002153430 'UISV-distributing-edge' V:[UIView:0x7ff2d6c116e0]-(0)-[_UIOLAGapGuide:0x600003e15e00'UISV-distributing']   (active)>",
    "<NSLayoutConstraint:0x600002151f40 'UISV-distributing-edge' _UIOLAGapGuide:0x600003e15e00'UISV-distributing'.bottom == UIView:0x7ff2d6c12810.top   (active)>",
    "<NSLayoutConstraint:0x600002164aa0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide']-(83)-|   (active, names: '|':UIView:0x7ff2f6d1d990 )>",
    "<NSLayoutConstraint:0x600002153480 'UIView-Encapsulated-Layout-Height' UIView:0x7ff2f6d1d990.height == 844   (active)>",
    "<NSLayoutConstraint:0x600002164a00 'UIView-topMargin-guide-constraint' V:|-(91)-[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide']   (active, names: '|':UIView:0x7ff2f6d1d990 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600002164730 UIView:0x7ff2d6c12810.height == 633   (active)>

标签: iosswiftautolayout

解决方案


您似乎将堆栈视图的顶部和底部锚定到 layoutMArginGuide,它固有地设置了高度,并且还手动设置了高度。充其量,如果这两个值完全匹配,这是矫枉过正的,如果它们相差一个点的一小部分,它将产生一个无法满足的约束。失去明确的高度约束。


推荐阅读