Search code examples
iosswiftuitableviewautolayoutsnapkit

SnapKit and Dynamic UITableViewCell not being laid out correctly


I'm currently building a reusable view that takes advantage of the dynamic resizing that UITableView has on offer with its cells.

What I'm trying to achieve is to give a view within the cell a width and a height depending on the size it has been given within the size property that is defined within a struct, I pass this through using a configure function, after setting the size of the view.

I then center it on the xAxis and apply any margins around the view using a property within the struct which is just a UIEdgeInset property. Using the SnapKit library this looks like this.

    if  let formImageItem = formImageItem,
        let size = formImageItem.size {

        formItemImgVw = UIImageView(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        formItemImgVw?.image = formImageItem.image
        formItemImgVw?.contentMode = formImageItem.aspectFit

        contentView.addSubview(formItemImgVw!)

        formItemImgVw?.snp.makeConstraints({ (make) in
              make.size.equalTo(CGSize(width: size.width, height: size.height))
              make.top.equalTo(formImageItem.margin.top)
              make.bottom.equalTo(formImageItem.margin.bottom)
              make.centerX.equalToSuperview()
        })
    }

The issue I seem to be having is i'm getting the following warning.

2018-10-12 14:57:34.101532+0100 xxxx Dev[6104:2160548] [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. 
(
    "<SnapKit.LayoutConstraint:[email protected]#61 UIImageView:0x10530a940.height == 114.0>",
    "<SnapKit.LayoutConstraint:[email protected]#62 UIImageView:0x10530a940.top == UITableViewCellContentView:0x105503500.top>",
    "<SnapKit.LayoutConstraint:[email protected]#63 UIImageView:0x10530a940.bottom == UITableViewCellContentView:0x105503500.bottom>",
    "<NSLayoutConstraint:0x2837e2580 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x105503500.height == 44   (active)>"
)

Will attempt to recover by breaking constraint 
<SnapKit.LayoutConstraint:[email protected]#61 UIImageView:0x10530a940.height == 114.0>

I understand what this is telling me basically that it's choosing to use the height 44 that is set by default for a table view cell. But I can't seem to get my head around why it's using this default height rather than the one that I have defined within my constraints and applying the height to the view whilst also adding the spacing to the top and bottom.

Also when using the debugger to inspect the UI it seems like a height isn't being set at all and as you can see the height of 44 is just clipping the entire imageview.

enter image description here

So ultimately what I'm trying to achieve is the ability to give a view a defined height and width, and use values to apply top and bottom spacing(margins) in order to resize the cell that it's currently within.


Solution

  • You need to lower the priority of the bottom constraints so replace this

    make.bottom.equalTo(formImageItem.margin.bottom)
    

    with

    make.bottom.equalTo(formImageItem.margin.bottom).priority(999)
    

    plus in viewDidLoad

    tableView.estimatedRowHeight = 120 
    tableView.rowHeight = UITableViewAutomaticDimension
    

    abd don't implement heightForRowAt