2

A UITableViewCell contains an UIImageView and has the height UITableViewAutomaticDimension.

I want to resize the image view according to the size of its image. The image view should then resize the height of the table view cell.

The vertical layout constraints of the image view in Interface Builder are:

  • imageView.topAnchor = cell.contentView.topAnchor
  • imageView.bottomAnchor <= cell.contentView.bottomAnchor + 10
  • imageView.heightAnchor = 100

I've set a layout constraint as IBOutlet for the height anchor of the image view. As soon as I change its constant the layout breaks and the constraint is ignored. The height of the table view cell does not adapt its size and seems to break the constraint.

The constraint constant is changed at:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! MyCell
    cell.image = image
    cell.updateConstraint()
    return cell
}

class MyCell {

    func updateConstraint() {
        imageViewHeightConstraint.constant = image.size.height // This line already throws the UIViewAlertForUnsatisfiableConstraints exception
        imageImageView.setNeedsLayout()
    }
}

How is it done properly?

Update: The error log break the "width = height" constraint because the layout is actually a bit more complicated then described above: The widthAnchors' constant is changed and the widthAnchor = heightAnchor of the image view.

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:0x7f98be1a22b0 H:[UIImageView:0x7f98be7d36e0(96)]>",
    "<NSLayoutConstraint:0x7f98be158470 UIImageView:0x7f98be7d36e0.width == UIImageView:0x7f98be7d36e0.height>",
    "<NSLayoutConstraint:0x7f98be1273e0 V:|-(5)-[UIImageView:0x7f98be7d36e0]   (Names: '|':UIView:0x7f98be12d860 )>",
    "<NSLayoutConstraint:0x7f98be133040 V:[UIImageView:0x7f98be7d36e0]-(5)-|   (Names: '|':UIView:0x7f98be12d860 )>",
    "<NSLayoutConstraint:0x7f98be1929e0 V:|-(5)-[UIView:0x7f98be12d860]   (Names: '|':UITableViewCellContentView:0x7f98be1582f0 )>",
    "<NSLayoutConstraint:0x7f98be12dd10 V:[UIView:0x7f98be12d860]-(>=10)-|   (Names: '|':UITableViewCellContentView:0x7f98be1582f0 )>",
    "<NSLayoutConstraint:0x7f98be7d66a0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f98be1582f0(89)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7f98be158470 UIImageView:0x7f98be7d36e0.width == UIImageView:0x7f98be7d36e0.height>

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.
Manuel
  • 14,274
  • 6
  • 57
  • 130
  • Possible duplicate of [Using Auto Layout in UITableView for dynamic cell layouts & variable row heights](http://stackoverflow.com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights) – Lou Franco Apr 13 '16 at 15:48
  • @Rob I updated my question, UIViewAlertForUnsatisfiableConstraints exception is thrown in the console. – Manuel Apr 13 '16 at 16:22
  • @LouFranco Thanks for the reference, I have read the post and it didn't help me with my specific problem. – Manuel Apr 13 '16 at 16:24
  • @Manuel did you try telling the UITableView about the updates via -beginUpdates etc? I think that should work – Bensge Apr 13 '16 at 16:36
  • You don't need `setNeedsLayout` because you're doing this synchronously (and you'd generally do `layoutIfNeeded()`, not `setNeedsLayout()`). You say you're getting an exception with the changing constraint. That's generally accompanied with a message of the console, describing the nature of the problem. Do you not have this lengthy log? – Rob Apr 13 '16 at 16:38
  • @Rob I updated the question with the error log. However, the exception is already thrown on the line where i change the constant. – Manuel Apr 13 '16 at 19:24
  • Understood. But it's only by looking at this log that you can diagnose _why_ you're getting that exception. It looks like the problem is that `UIView-Encapsulated-Layout-Height`, which is conflicting with your image view-based vertical constraints. Pursuant to that link that Lou shared with you, did you set the `estimatedRowHeight`, too? – Rob Apr 13 '16 at 19:28
  • @LouFranco beginUpdates() is for group animation of insertion, deletion or selection operations on the tableView, that is not what I am doing. Still tried it but it had no effect. – Manuel Apr 13 '16 at 19:31
  • @Rob Yes, estimatedRowHeight is set as property of the tableView. I have other custom cells inside the table view where the auto-layout constraints do not change and they work fine. It's only the cell with constraint change that causes problems. I am guessing the solution is lowing the property of another constraint. The contentHugging priority of the cell and its contentView is 250, the content compression resistance priority is 750. My other custom constraints in Interface Builder are prio 1000, so that seems fine. – Manuel Apr 13 '16 at 19:33
  • Fascinating, as when I last did this, setting `estimatedRowHeight` to non-zero value and setting `rowHeight` To `UITableViewAutomaticDimension` worked, but I just repeated it and see the same problem as you do: An error re the constraints, but when you look at the numbers in the error message, everything adds up fine. I reduced the priority of the height constraint, though, and the error went away (and the height was correct!). It looks like it's determining there is a problem that isn't really there. There's got to be a better way to do this, but lowering the height constraint priority works. – Rob Apr 13 '16 at 20:39
  • @Rob I tried setting the priority of the height constraint to 999 and the exception went away. However the cell would have the default (?) height which was too small for the image. When scrolling the table view and the cell reappeared, it had the correct size however. So the problem I'm left with is getting the table view to relayout the cell immediately. It doesn't help when I call layoutIfNeeded() on the cell or the imageView inside the cell. – Manuel Apr 13 '16 at 20:43
  • When I set the initial height of the imageView larger than the image height then i don't get the exception but the cell is also not resized so i have a white gap below the cell. The gap is gone after scrolling when the cell reappears. – Manuel Apr 13 '16 at 21:05
  • If tweaking the image view height constraint priority changed the layout, then maybe change one of your other vertical priorities to a lower priority (e.g. one of the leading top constraints) and keep image view height at 1000. – Rob Apr 14 '16 at 16:20

0 Answers0