所以我有一个UIViewController,UICollectionViewCompositionalLayout其中一个部分(最后一个)是一个列表。我UICollectionViewListCell为它配置了 2 个,但其中一个有问题(这个UICollectionView里面有一个)。不幸的是,我在控制台中遇到了配置错误:
[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.
(
"<NSLayoutConstraint:0x7b14000adb10 V:|-(12)-[UIImageView:0x7b500017f800] (active, names: '|':UIView:0x7b4800149700 )>",
"<NSLayoutConstraint:0x7b14000adf20 UIImageView:0x7b500017f800.height == 20 (active)>",
"<NSLayoutConstraint:0x7b14000adf70 V:[UIImageView:0x7b500017f800]-(>=20)-| (active, names: '|':UIView:0x7b4800149700 )>",
"<NSLayoutConstraint:0x7b14000a0960 'UIView-Encapsulated-Layout-Height' UIView:0x7b4800149700.height == 44 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7b14000adf70 V:[UIImageView:0x7b500017f800]-(>=20)-| (active, names: '|':UIView:0x7b4800149700 )>
[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.
(
"<NSLayoutConstraint:0x7b14000aea60 UICollectionView:0x7b7800092400.height == 50 (active)>",
"<NSLayoutConstraint:0x7b14000a29e0 V:|-(12)-[UILabel:0x7b5400172000] (active, names: '|':UIView:0x7b4800155b80 )>",
"<NSLayoutConstraint:0x7b14000aea10 V:[UILabel:0x7b5400172000]-(15)-[UILabel:0x7b5400173680] (active)>",
"<NSLayoutConstraint:0x7b14000aeab0 V:[UILabel:0x7b5400173680]-(15)-[UICollectionView:0x7b7800092400] (active)>",
"<NSLayoutConstraint:0x7b14000aeba0 UICollectionView:0x7b7800092400.bottom <= UIView:0x7b4800155b80.bottom - 12 (active)>",
"<NSLayoutConstraint:0x7b1400053de0 'UIView-Encapsulated-Layout-Height' UIView:0x7b4800155b80.height == 44 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7b14000aea60 UICollectionView:0x7b7800092400.height == 50 (active)>
如您所见,UIView-Encapsulated-Layout-Height返回默认值 44 而不是计算得出的值(应该在 144 左右)。
这是我的单元格配置,在配置列表单元格时有什么明显的或者我遗漏了什么吗?
class ActivityFeedAchievementListCell: UICollectionViewListCell {
static let reuseIdentifier = "ActivityFeedAchievementListCell"
private(set) var activity: UserActivity?
let avatar: UIImageView = {
let iconView = UIImageView(frame: .zero)
iconView.contentMode = .scaleAspectFill
iconView.layer.cornerRadius = 15.0
iconView.layer.masksToBounds = true
return iconView
}()
private let userNameLabel: UILabel = {
let label = UILabel()
label.font = UIFontMetrics(forTextStyle: .title1).scaledFont(for: UIFont(name: "Lato-Regular", size: 16.0)!)
label.textColor = .white
return label
}()
let platform: UIImageView = {
let iconView = UIImageView(frame: .zero)
iconView.contentMode = .scaleAspectFit
return iconView
}()
private let timeLabel: UILabel = {
let label = UILabel()
label.font = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: UIFont(name: "Lato-Light", size: 18.0)!)
label.textColor = UIColor(white: 1.0, alpha: 0.5)
return label
}()
private let descriptionLabel: UILabel = {
let label = UILabel()
label.font = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: UIFont(name: "Lato-Light", size: 18.0)!)
label.textColor = .white
label.numberOfLines = 0
return label
}()
private let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.minimumInteritemSpacing = 0.0
layout.minimumLineSpacing = 12.0
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.register(SingleAchievementCell.self, forCellWithReuseIdentifier: SingleAchievementCell.reuseIdentifier)
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.backgroundColor = .clear
return collectionView
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = .clear
self.setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func updateConfiguration(using state: UICellConfigurationState) {
self.backgroundConfiguration = UIBackgroundConfiguration.clear()
}
private func setupViews() {
let bgColorView = UIView()
bgColorView.backgroundColor = UIColor(white: 1.0, alpha: 0.05)
self.selectedBackgroundView = bgColorView
self.backgroundColor = .clear
self.contentView.addSubviews(views: self.avatar, self.userNameLabel, self.platform, self.timeLabel, self.descriptionLabel, self.collectionView)
self.avatar.translatesAutoresizingMaskIntoConstraints = false
self.userNameLabel.translatesAutoresizingMaskIntoConstraints = false
self.platform.translatesAutoresizingMaskIntoConstraints = false
self.timeLabel.translatesAutoresizingMaskIntoConstraints = false
self.descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
self.collectionView.translatesAutoresizingMaskIntoConstraints = false
self.collectionView.delegate = self
self.collectionView.dataSource = self
NSLayoutConstraint.activate([
self.avatar.widthAnchor.constraint(equalToConstant: 30.0),
self.avatar.heightAnchor.constraint(equalToConstant: 30.0),
self.avatar.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 12.0),
self.avatar.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20.0),
self.userNameLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 12.0),
self.userNameLabel.leftAnchor.constraint(equalTo: self.avatar.rightAnchor, constant: 15.0),
self.platform.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 12.0),
self.platform.leftAnchor.constraint(equalTo: self.userNameLabel.rightAnchor, constant: 15.0),
self.timeLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 12.0),
self.timeLabel.leftAnchor.constraint(equalTo: self.platform.rightAnchor, constant: 15.0),
self.timeLabel.rightAnchor.constraint(lessThanOrEqualTo: self.contentView.rightAnchor, constant: -20.0),
self.descriptionLabel.topAnchor.constraint(equalTo: self.userNameLabel.bottomAnchor, constant: 15.0),
self.descriptionLabel.leftAnchor.constraint(equalTo: self.avatar.rightAnchor, constant: 15.0),
self.descriptionLabel.rightAnchor.constraint(lessThanOrEqualTo: self.contentView.rightAnchor, constant: -20.0),
self.collectionView.heightAnchor.constraint(equalToConstant: 50.0),
self.collectionView.topAnchor.constraint(equalTo: self.descriptionLabel.bottomAnchor, constant: 15.0),
self.collectionView.leftAnchor.constraint(equalTo: self.avatar.rightAnchor, constant: 15.0),
self.collectionView.rightAnchor.constraint(lessThanOrEqualTo: self.contentView.rightAnchor, constant: -20.0),
self.collectionView.bottomAnchor.constraint(lessThanOrEqualTo: self.contentView.bottomAnchor, constant: -12.0)
])
}
override func prepareForReuse() {
super.prepareForReuse()
self.activity = nil
}
func configure(with item: ActivityGameItem) {
if let activity = item.activity {
self.activity = item.activity
self.platform.image = UIImage(named: activity.gameReleaseKey.platform.userReadable())
self.timeLabel.text = activity.eventTime
self.descriptionLabel.attributedText = activity.description
}
if let user = item.user {
if let avatar = user.imageUrl {
self.avatar.af.setImage(withURL: avatar)
}
self.userNameLabel.text = user.username
}
self.collectionView.reloadData()
}
}
// MARK: - UICollectionViewDataSource
extension ActivityFeedAchievementListCell: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard let activity = self.activity, let achievements = activity.achievements else { return 0 }
return achievements.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SingleAchievementCell.reuseIdentifier, for: indexPath) as! SingleAchievementCell
guard let activity = self.activity, let achievements = activity.achievements else { return cell }
let item = achievements[indexPath.item]
if let url = URL(string: item.imageURLUnlocked) {
cell.achievementView.af.setImage(withURL: url)
}
return cell
}
}
// MARK: - UICollectionViewDelegateFlowLayout
extension ActivityFeedAchievementListCell: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 50.0, height: 50.0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0, right: 0.0)
}
}
// MARK: - UICollectionViewDelegate
extension ActivityFeedAchievementListCell: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let activity = self.activity, let achievements = activity.achievements else { return }
let achievement = achievements[indexPath.item]
log.info("Selected achievement with id: '\(achievement.achievementId)'.")
}
}