Search code examples
iosswiftuiviewautolayout

Swift - UIView with constraint of zero height - error


I have UIView with height constraint. I want to hide this view, so I set height constraint constant to 0.

I am setting constraint in code inside extended UIView:

_height = self.heightAnchor.constraint(equalToConstant: 50)

NSLayoutConstraint.activate([

        _closeBtn.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5),
        _closeBtn.topAnchor.constraint(equalTo: self.topAnchor, constant: 10),
        _closeBtn.heightAnchor.constraint(equalTo: _centerLabel.heightAnchor),
        _closeBtn.widthAnchor.constraint(equalTo: _closeBtn.heightAnchor),

        _centerLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 10),
        _centerLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5),
        _centerLabel.leadingAnchor.constraint(equalTo: _closeBtn.trailingAnchor),
        _centerLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -16),

        _height
    ])

Now, If I change _height.constant = 0, I have got this error:

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x146a374c0 UIButton:0x147615b00'X'.width == UIButton:0x147615b00'X'.height   (active)>",
    "<NSLayoutConstraint:0x146a37530 UIButton:0x147615b00'X'.height == UILabel:0x147615e80.height   (active)>",
    "<NSLayoutConstraint:0x146a37450 V:|-(20)-[UILabel:0x147615e80]   (active, names: '|':InternetConnectionInfoView:0x14742f600 )>",
    "<NSLayoutConstraint:0x146a373e0 UILabel:0x147615e80.bottom == InternetConnectionInfoView:0x14742f600.bottom - 5   (active)>",
    "<NSLayoutConstraint:0x146a37680 InternetConnectionInfoView:0x14742f600.height == 0   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x146a374c0 UIButton:0x147615b00'X'.width == UIButton:0x147615b00'X'.height   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x146a37530 UIButton:0x147615b00'X'.height == UILabel:0x147615e80.height   (active)>",
    "<NSLayoutConstraint:0x146a37450 V:|-(20)-[UILabel:0x147615e80]   (active, names: '|':InternetConnectionInfoView:0x14742f600 )>",
    "<NSLayoutConstraint:0x146a373e0 UILabel:0x147615e80.bottom == InternetConnectionInfoView:0x14742f600.bottom - 5   (active)>",
    "<NSLayoutConstraint:0x146a37680 InternetConnectionInfoView:0x14742f600.height == 0   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x146a373e0 UILabel:0x147615e80.bottom == InternetConnectionInfoView:0x14742f600.bottom - 5   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

I suspect, that this comes from top and bottom anchor being set to constant values. I have tried to use greaterThanOrEual / lessThanOrEqual, but it destroys the layout.

How to solve this (eg. hiding UIView)? I cannot set isHidden, because other UIViews are anchored to the bottom of this view and they need to move upon hiding.


Solution

  • This is a constraint conflict, consider reducing the constraint priority can help you fix this issue.

    let closeBtnTopAnchor = _closeBtn.topAnchor.constraint(greaterThanOrEqualTo: self.topAnchor)
    let closeBtnTopAnchorWithLowPriority = _closeBtn.topAnchor.constraint(equalTo: self.topAnchor, constant: 10)
    closeBtnTopAnchorWithLowPriority.priority = UILayoutPriorityDefaultHigh
    
    let centerLabelTopAnchor = _centerLabel.topAnchor.constraint(greaterThanOrEqualTo: self.topAnchor)
    let centerLabelTopAnchorWithLowPriority = _centerLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 10)
    centerLabelTopAnchorWithLowPriority.priority = UILayoutPriorityDefaultHigh
    
    let centerLabelBottomAnchor = _centerLabel.bottomAnchor.constraint(lessThanOrEqualTo: self.bottomAnchor)
    let centerLabelBottomAnchorWithLowPriority = _centerLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5)
    centerLabelBottomAnchorWithLowPriority.priority = UILayoutPriorityDefaultHigh
    
    NSLayoutConstraint.activate([
    
       _closeBtn.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5),
       closeBtnTopAnchor,
       closeBtnTopAnchorWithLowPriority,
    
       _closeBtn.heightAnchor.constraint(equalTo: _centerLabel.heightAnchor),
       _closeBtn.widthAnchor.constraint(equalTo: _closeBtn.heightAnchor),
    
       centerLabelTopAnchor,
       centerLabelTopAnchorWithLowPriority,
       centerLabelBottomAnchor,
       centerLabelBottomAnchorWithLowPriority,
       _centerLabel.leadingAnchor.constraint(equalTo: _closeBtn.trailingAnchor),
       _centerLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -16),
    
       _height
       ])