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 Output2019-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
Replies
Boosts
Views
Activity
We are building an app that aggregates information about lots of businesses. For businesses that opt in, we would like to provide them with a custom App Clip experience.
Considering the scale at which we plan to operate, is it possible to create and update App Clip experiences programmatically? The AppStoreConnect API seems to have no mention of App Clips.
This is not something we can do manually for every business partner, so inability to automate it will result in our plans to adopt App Clips being delayed.
Thanks!