Autolayout issue with Compositional Layout

I have a constraint on my `UIImageView` that is being broken, but I don't understand why. It appears that it is due to the `estimated` item size on my collection view's compositional layout. Any thoughts would be greatly appreciated.


Note: code formatting appears to be messed up after pasting, apologies for that.


Cell and Layout Section Definition


//
// PostCell.swift
//
// Created by Sam Jackson on 10/13/19.
// Copyright © 2019 Vita. All rights reserved.
//

import UIKit
import Logging
import Kingfisher
import Foundation

// MARK: PostCell

class PostCell: UICollectionViewCell {
  static let reuseIdentifier = "PostCell"
  static let authorPhotoSize: CGFloat = 64.0
   
  /// The post that drives the content of this `UICollectionViewCell`. When this
  /// property is set, the content of the cell will change.
  var post: Post! {
  didSet {
  displayNameLabel.text = post.author.displayName
  metadataLabel.text = "This is a test."
  authorPhotoImageView.kf.setImage(with: post.author.photoURL)
  }
  }
   
  /// Display name of the post author.
  var displayNameLabel: UILabel = {
  let label = UILabel()
  label.translatesAutoresizingMaskIntoConstraints = false
  label.font = UIFont.systemFont(ofSize: 20, weight: .medium)
  label.textColor = .label
  return label
  }()
   
  /// Typically shows the timestamp for the post.
  var metadataLabel: UILabel = {
  let label = UILabel()
  label.translatesAutoresizingMaskIntoConstraints = false
  label.font = UIFont.systemFont(ofSize: 16, weight: .regular)
  label.textColor = .gray
  return label
  }()
   
  /// Profile photo of the post author.
  var authorPhotoImageView: UIImageView = {
  let imageView = UIImageView()
  imageView.contentMode = .scaleAspectFill
  imageView.translatesAutoresizingMaskIntoConstraints = false
  imageView.layer.cornerRadius = PostCell.authorPhotoSize / 2
  imageView.clipsToBounds = true
  return imageView
  }()
   
  /// This `UIStackView` organizes the labels in the post header. Specifically, it arranges
  /// the `displayNameLabel` and `metadataLabel` in a vertical stack.
  lazy var headerLabelStack: UIStackView = {
  let stack = UIStackView(
  arrangedSubviews: [displayNameLabel, metadataLabel]
  )
  stack.translatesAutoresizingMaskIntoConstraints = false
  stack.axis = .vertical
  return stack
  }()
   
  /// This `UIStackView` composes the different elements of the post header. Specifically,
  /// it arranges the `authorPhotoImageView` and `headerLabelStack` in a horizontal stack.
  lazy var headerStack: UIStackView = {
  let stack = UIStackView(
  arrangedSubviews: [authorPhotoImageView, headerLabelStack]
  )
  stack.translatesAutoresizingMaskIntoConstraints = false
  stack.alignment = .center
  stack.axis = .horizontal
  stack.spacing = 8
  return stack
  }()
   
  /// This is the all-encompassing stack for a `Post`. By default, it comprises of a header and footer.
  /// It can be configured to contain different elements of a post, such as a photo or video.
  lazy var postStack: UIStackView = {
  let stack = UIStackView(
  arrangedSubviews: [headerStack]
  )
  stack.translatesAutoresizingMaskIntoConstraints = false
  stack.axis = .vertical
  stack.spacing = 8
  return stack
  }()
   
  /// Update the data presented in the cell with some `Post`.
  func configure(with post: Post) {
  self.post = post
  }
   
  override init(frame: CGRect) {
  super.init(frame: frame)
   
  // All other subviews are managed by stacks.
  contentView.addSubview(postStack)
   
  // Activate all necessary constraints.
  NSLayoutConstraint.activate([
  authorPhotoImageView.heightAnchor.constraint(equalToConstant: PostCell.authorPhotoSize),
  authorPhotoImageView.widthAnchor.constraint(equalToConstant: PostCell.authorPhotoSize),
  postStack.topAnchor.constraint(equalTo: contentView.topAnchor),
  postStack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
  postStack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
  contentView.bottomAnchor.constraint(equalTo: postStack.bottomAnchor)
  ])
  }
   
  required init?(coder: NSCoder) {
  fatalError("init(coder:) has not been implemented")
  }
}

// MARK: DefinesLayoutSection

extension PostCell {
   
  /// Because all posts will be presented the same way within a hosting `UICollectionView`,
  /// we statically define their layout section here.
  static func getLayoutSection(withDivider: Bool = false) -> NSCollectionLayoutSection {
   
  // Each cell should span the width of the collection view.
  // The height of the cell should be dynamic.
  let item = NSCollectionLayoutItem(
  layoutSize: NSCollectionLayoutSize(
  widthDimension: .fractionalWidth(1.0),
  heightDimension: .estimated(44.0)
  )
  )
   
  // We aren't doing anything with groups at this time, so we leave
  // these settings the same as those for the `NSCollectionLayoutItem`.
  let groupSize = NSCollectionLayoutSize(
  widthDimension: .fractionalWidth(1.0),
  heightDimension: .estimated(44.0)
  )
  let group = NSCollectionLayoutGroup.vertical(
  layoutSize: groupSize,
  subitem: item,
  count: 1
  )
   
  // Insets for the section should match our other sections.
  let section = NSCollectionLayoutSection(group: group)
  section.contentInsets = NSDirectionalEdgeInsets(
  top: 0,
  leading: 17,
  bottom: 0,
  trailing: 17
  )
   
  // Space between cells.
  section.interGroupSpacing = 17.0
   
  return section
  }
}

Console Output


2019-10-13 21:03:41.424629-0400 [6217:1241993] [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. 
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
  "<NSAutoresizingMaskLayoutConstraint:0x28312fb60 h=--& v=--& UIView:0x10c7bef60.height == 44 (active)>",
  "<NSLayoutConstraint:0x28312caf0 UIImageView:0x10c7beda0.height == 64 (active)>",
  "<NSLayoutConstraint:0x28312cb90 V:|-(0)-[UIStackView:0x10c7bf580] (active, names: '|':UIView:0x10c7bef60 )>",
  "<NSLayoutConstraint:0x28312cc80 V:[UIStackView:0x10c7bf580]-(0)-| (active, names: '|':UIView:0x10c7bef60 )>",
  "<NSLayoutConstraint:0x28312f7a0 'UISV-canvas-connection' UIStackView:0x10c7bf400.top == _UILayoutSpacer:0x282d663a0'UISV-alignment-spanner'.top (active)>",
  "<NSLayoutConstraint:0x28312f840 'UISV-canvas-connection' UIStackView:0x10c7bf400.centerY == UIImageView:0x10c7beda0.centerY (active)>",
  "<NSLayoutConstraint:0x28312f930 'UISV-canvas-connection' UIStackView:0x10c7bf580.top == UIStackView:0x10c7bf400.top (active)>",
  "<NSLayoutConstraint:0x28312f980 'UISV-canvas-connection' V:[UIStackView:0x10c7bf400]-(0)-| (active, names: '|':UIStackView:0x10c7bf580 )>",
  "<NSLayoutConstraint:0x28312f610 'UISV-spanning-boundary' _UILayoutSpacer:0x282d663a0'UISV-alignment-spanner'.top <= UIImageView:0x10c7beda0.top (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x28312caf0 UIImageView:0x10c7beda0.height == 64 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Post not yet marked as solved Up vote post of sroth Down vote post of sroth
2.9k views

Replies

Was this ever resolved? Facing a similar issue.

Setting the priority of the bottom or trailing constraint (based on you want dynamic height or dynamic width) to 999 solved the problem for me.

@szaboagoston's answer solved it for me.