I was running through the same issue when it came to embedding a UIStackView with a horizontal axis and center alignment in a UICollectionViewCell, it turns out it is an issue with UIStackView in general not just when it is inside a UICollectionViewCell
I figured out a way to fix the issue by adding an extra arrangedSubview to the UIStackView and giving it a width of 0 and a height of 0, coupled with 0 spacing, making the view invisible. This resolves the issue of the height ambiguity for some reason. Here's the test viewcontroller I used to test this theory. Every time you press the button it flips the state from the size being 1.7976931348623157e+308 to the actual height
class ViewController: UIViewController {
let stackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.alignment = .center
return stackView
}()
let label = UILabel()
let someView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.center = view.center
label.textAlignment = .center
label.backgroundColor = .orange
label.text = "This is text"
stackView.addArrangedSubview(label)
let button = UIButton(primaryAction: UIAction(handler: { [weak self] action in
self?.buttonPressed()
}))
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.topAnchor.constraint(equalTo: stackView.bottomAnchor),
someView.heightAnchor.constraint(equalToConstant: 0),
someView.widthAnchor.constraint(equalToConstant: 0),
])
button.setTitle("Flip State", for: .normal)
}
func buttonPressed() {
if someView.superview != nil {
stackView.removeArrangedSubview(someView)
someView.removeFromSuperview()
} else {
stackView.addArrangedSubview(someView)
}
let size = stackView.systemLayoutSizeFitting(.init(width: view.frame.width, height: .greatestFiniteMagnitude),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel)
label.text = "\(size)"
}
}
I hope this helps someone out there cause I just wasted a full day's work on something as stupid as this