2

I'm using Masonry in my UITableViewCell, the cell has two subviews, one is contentLabel, the other one is imageView. While the imageView is not always present, if the cell has one image url, present it, or hide. If the imageView is hidden, I want to set the contentLabel to cell.contentView.bottom to another value, something is like below:

  [_contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(self.contentView.mas_left);
    make.top.equalTo(self.contentView.mas_bottom).offset(20);
    make.right.equalTo(self.contentView.mas_right).offset(-6);
    _bottomConstraint = make.bottom.equalTo(_imageView.mas_top).offset(-14);
  }];

  [_imageView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(_contentLabel.mas_left);
    make.bottom.equalTo(self.contentView.mas_bottom).offset(-14);
  }];

  if (tweet.imageUrl) {
    _imageView.hidden = NO;
    [_imageView sd_setImageWithURL:tweet.imageUrl placeholderImage:[UIImage imageNamed:@"loading"] options:0];
  } else {
    _imageView.hidden = YES;
    [_imageView sd_setImageWithURL:NULL];
  }

  if (_imageView.hidden) {
    [_contentLabel mas_updateConstraints:^(MASConstraintMaker *make) {
      make.bottom.equalTo(_imageView.mas_top).offset(0);
    }];
  }

But I always got Error msg below:

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. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<MASLayoutConstraint:0x7fef9cd178d0 UILabel:0x7fef9cd437e0.bottom == UIImageView:0x7fef9cd26260.top - 14>",
    "<MASLayoutConstraint:0x7fef9caf5430 UILabel:0x7fef9cd437e0.bottom == UIImageView:0x7fef9cd26260.top>"
)

Will attempt to recover by breaking constraint 
<MASLayoutConstraint:0x7fef9caf5430 UILabel:0x7fef9cd437e0.bottom == UIImageView:0x7fef9cd26260.top>

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.

That seems mas_updateConstraints didn't remove the old constraint, but add a new constraint, the two conflicted each other. So how could I update the constraint value dynamically based in runtime?

jsvisa
  • 2,987
  • 2
  • 24
  • 30

1 Answers1

1

Maybe this was not your problem, but it might help others:

My problem was essentially the following:

I assigned first a height constraint to a subclass of UIView:

make.height.equalTo(label); // label is another subclass of UIView

Later, I tried to „update“ this constraint using:

make.height.equalTo(@(newHeight)); // newHeight is a CGFloat  

This left the original constraint installed, and added a new constraint that conflicted with the 1st one.

I then changed the assignment of the 1st constraint to:

CGFloat labelHeight = label.frame.size.height;
make.height.equalTo(@(labelHeight)); 

…and the conflict was gone.

Apparently, iOS Masonry cannot update a constraint defined by a UIView by a constraint defined by a NSNumber.

Reinhard Männer
  • 14,022
  • 5
  • 54
  • 116