Ios 自定义UICollectionView单元格中的问题更新约束
我在更新collectionView单元格中约束的锚定时遇到问题。我有两种观点,分别代表了主队和客队进球总数的百分比 当我第一次查看统计数据时,一切正常,我在控制台中得到了正确的打印语句(例如,对于索引0,Width HomeCell:139.0和Width AwayCell:27.0)。当我回到我的pitchViewController并添加更多目标时,我得到一个错误,两个条消失 我已经尝试在两个条形图视图上调用layoutIfNeeded()或setNeedsLayout()。但到目前为止还没有奏效 这是我的控制台输出,下面是相关代码:Ios 自定义UICollectionView单元格中的问题更新约束,ios,swift,uicollectionview,constraints,uicollectionviewcell,Ios,Swift,Uicollectionview,Constraints,Uicollectionviewcell,我在更新collectionView单元格中约束的锚定时遇到问题。我有两种观点,分别代表了主队和客队进球总数的百分比 当我第一次查看统计数据时,一切正常,我在控制台中得到了正确的打印语句(例如,对于索引0,Width HomeCell:139.0和Width AwayCell:27.0)。当我回到我的pitchViewController并添加更多目标时,我得到一个错误,两个条消失 我已经尝试在两个条形图视图上调用layoutIfNeeded()或setNeedsLayout()。但到目前为止还
Width HomeCell: 83.0
Width AwayCell: 83.0
[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:0x604000287440 UIView:0x7f870f461d50.width == 1 (active)>",
"<NSLayoutConstraint:0x60c00009a810 UIView:0x7f870f461d50.width == 83 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x60c00009a810 UIView:0x7f870f461d50.width == 83 (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
我的统计数据收集视图
import UIKit
class GameStatistics: NSObject, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
let blackView = UIView()
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = UIColor.white
return cv
}()
let cellId = "cellId"
let sectionHeader = "sectionHeader"
let sectionFooter = "sectionFooter"
let cellHeight: CGFloat = 40
let headerHeight: CGFloat = 80
let footerHeight: CGFloat = 50
let cellSpacing: CGFloat = 0
var statistics = [Statistic(name: "Tore", home: 0, away: 0, homeBar: 1.0, awayBar: 1.0), //Goals
Statistic(name: "Schüsse aufs Tor", home: 0, away: 0, homeBar: 1.0, awayBar: 1.0), //Shots on Target
Statistic(name: "Schüsse neben das Tor", home: 0, away: 0, homeBar: 1.0, awayBar: 1.0), //Shots off Target
Statistic(name: "Freistöße", home: 0, away: 0, homeBar: 1.0, awayBar: 1.0), //Free Kicks
Statistic(name: "Eckbälle", home: 0, away: 0, homeBar: 1.0, awayBar: 1.0), //Corner Kicks
Statistic(name: "Fouls", home: 0, away: 0, homeBar: 1.0, awayBar: 1.0), //Fouls
Statistic(name: "Abseits / Mittellinie", home: 0, away: 0, homeBar: 1.0, awayBar: 1.0), //Offside / Centerline
Statistic(name: "Strafen", home: 0, away: 0, homeBar: 1.0, awayBar: 1.0)] //Cautions
var barWidthHome: CGFloat = 1.0
var barWidthAway: CGFloat = 1.0
var statisticValueSum: Int = 1
var valueHomeTeam: Int = 1
var valueAwayTeam: Int = 1
func updateGoals() {
valueHomeTeam = UserDefaults.standard.integer(forKey: "homegoals")
valueAwayTeam = UserDefaults.standard.integer(forKey: "awaygoals")
statisticValueSum = valueHomeTeam + valueAwayTeam
barWidthHome = CGFloat((Int(pitchWidth! / 2) - 40) * valueHomeTeam / statisticValueSum)
barWidthAway = CGFloat((Int(pitchWidth! / 2) - 40) * valueAwayTeam / statisticValueSum)
statistics[0] = Statistic(name: "Tore", home: valueHomeTeam, away: valueAwayTeam, homeBar: barWidthHome, awayBar: barWidthAway)
}
func showStatistics() {
if let window = UIApplication.shared.keyWindow {
blackView.backgroundColor = UIColor(white: 0, alpha: 0.5)
blackView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleDismiss)))
window.addSubview(blackView)
window.addSubview(collectionView)
// Dynamic Height of Collection View
let value: CGFloat = CGFloat(statistics.count)
let height: CGFloat = value * cellHeight + (value - 1) * cellSpacing + headerHeight + footerHeight
let y = window.frame.height - height
blackView.frame = window.frame
collectionView.frame = CGRect(x: 0, y: window.frame.height, width: window.frame.width, height: height)
blackView.alpha = 0
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.blackView.alpha = 1
self.collectionView.frame = CGRect(x: 0, y: y, width: self.collectionView.frame.width, height: self.collectionView.frame.height)
}, completion: nil)
}
}
@objc func handleDismiss() {
UIView.animate(withDuration: 0.5) {
self.blackView.alpha = 0
if let window = UIApplication.shared.keyWindow {
self.collectionView.frame = CGRect(x: 0, y: window.frame.height, width: self.collectionView.frame.width, height: self.collectionView.frame.height)
}
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return statistics.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! GameStatisticCell
cell.statistic = statistics[indexPath.item]
cell.layoutIfNeeded()
//dump(statistics)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: cellHeight)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return cellSpacing
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return cellSpacing
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let supplementaryView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: sectionHeader, for: indexPath)
return supplementaryView
case UICollectionElementKindSectionFooter:
let supplementaryView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: sectionFooter, for: indexPath)
return supplementaryView
default:
fatalError("Unexpected element kind")
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: headerHeight)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: footerHeight)
}
override init() {
super.init()
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(GameStatisticCell.self, forCellWithReuseIdentifier: cellId)
collectionView.register(GameStatisticHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: sectionHeader)
collectionView.register(GameStatisticFooter.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: sectionFooter)
}
}
您不应该添加新的约束,因为这些约束显然会与现有约束(不同的填充)冲突。您应该保留对在
setupCell
中创建的动态约束的引用,并且只在statistic didSet{}
中更新它们。通过两个帮助函数,我可以在我的statistic didSet中设置约束并更新它们。花了一些时间,但最后上述评论让我走上了正确的轨道。多谢各位
func updateHomeBar() {
homeWidth?.constant = barWidthHome
homeTeamStatisticBar.setNeedsLayout()
}
func homeBarConstraints() {
homeTeamStatisticBar.translatesAutoresizingMaskIntoConstraints = false
var homeConstraints: [NSLayoutConstraint] = [
homeTeamStatisticBar.topAnchor.constraint(equalTo: topAnchor, constant: 4),
homeTeamStatisticBar.rightAnchor.constraint(equalTo: rightAnchor, constant: -barCenter),
homeTeamStatisticBar.heightAnchor.constraint(equalToConstant: 16)]
homeWidth = homeTeamStatisticBar.widthAnchor.constraint(equalToConstant: barWidthHome)
homeConstraints.append(homeWidth!)
NSLayoutConstraint.activate(homeConstraints)
}
起初,我在setupCell()中设置了homeTeamStatisticBar和awayTeamStatisticBar的锚,标签的其他约束也在这里。但我无法在统计变量中更新它们。因此,如果能进一步帮助我走上正轨,我将不胜感激。
func updateHomeBar() {
homeWidth?.constant = barWidthHome
homeTeamStatisticBar.setNeedsLayout()
}
func homeBarConstraints() {
homeTeamStatisticBar.translatesAutoresizingMaskIntoConstraints = false
var homeConstraints: [NSLayoutConstraint] = [
homeTeamStatisticBar.topAnchor.constraint(equalTo: topAnchor, constant: 4),
homeTeamStatisticBar.rightAnchor.constraint(equalTo: rightAnchor, constant: -barCenter),
homeTeamStatisticBar.heightAnchor.constraint(equalToConstant: 16)]
homeWidth = homeTeamStatisticBar.widthAnchor.constraint(equalToConstant: barWidthHome)
homeConstraints.append(homeWidth!)
NSLayoutConstraint.activate(homeConstraints)
}