Ios 自定义UICollectionView单元格中的问题更新约束

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()。但到目前为止还

我在更新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)
}