Swift:UICollectionView随单元格数动态调高度的约束冲突问题
解决UICollectionView动态调整高度时的约束冲突问题
你遇到的问题其实很常见——每次点击按钮添加新单元格时,你都给UICollectionView新增了一个高度约束,但原来的旧约束并没有被移除,多个高度约束同时生效,系统无法判断该遵循哪一个,自然就抛出了约束冲突的错误。
核心解决方案:保存高度约束实例,动态修改其constant值
我们不需要每次添加新约束,而是把初始的高度约束保存为一个实例变量,之后只需要修改它的constant值即可,这样就不会产生重复约束的冲突。
修正后的完整代码
import UIKit class TestController: UIViewController, UICollectionViewDataSource { // 1. 将高度约束保存为实例变量,方便后续修改 private var collectionViewHeightConstraint: NSLayoutConstraint! let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) collectionView.backgroundColor = .white let cellWidth = UIScreen.main.bounds.width - 40 layout.minimumInteritemSpacing = 0 layout.minimumLineSpacing = 10 layout.itemSize = CGSize(width: cellWidth, height: 25) collectionView.collectionViewLayout = layout collectionView.translatesAutoresizingMaskIntoConstraints = false return collectionView }() var numberOfCells = 1 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return numberOfCells } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! Cell return cell } let addMoreCellButton: UIButton = { let button = UIButton() button.setTitle("Add more cell", for: .normal) // 修正拼写错误:falase → false button.translatesAutoresizingMaskIntoConstraints = false return button }() @objc func addMoreCell() { numberOfCells += 1 // 2. 直接修改已有约束的constant值,而非新增约束 collectionViewHeightConstraint.constant = CGFloat(numberOfCells * 35 - 10) collectionView.reloadData() } override func viewDidLoad() { super.viewDidLoad() collectionView.dataSource = self collectionView.register(Cell.self, forCellWithReuseIdentifier: "cell") view.addSubview(collectionView) // 批量激活约束,更简洁规范 NSLayoutConstraint.activate([ collectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0), collectionView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0), collectionView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0) ]) // 3. 创建并保存高度约束,激活它 collectionViewHeightConstraint = collectionView.heightAnchor.constraint(equalToConstant: 25) collectionViewHeightConstraint.isActive = true view.addSubview(addMoreCellButton) // 修正按钮约束的错误:把collectionView.topAnchor改成addMoreCellButton.topAnchor NSLayoutConstraint.activate([ addMoreCellButton.topAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: 20), addMoreCellButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0) ]) // 将addTarget移到viewDidLoad,避免闭包中self的潜在循环引用问题 addMoreCellButton.addTarget(self, action: #selector(addMoreCell), for: .touchUpInside) } } // 补充Cell类的基础实现(如果你的项目中已有可以忽略) class Cell: UICollectionViewCell { override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .lightGray } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
额外修正的细节问题
- 按钮的
translatesAutoresizingMaskIntoConstraints拼写错误(falase→false) - 按钮的约束写错了,误将
addMoreCellButton的topAnchor写成collectionView.topAnchor,导致按钮位置异常 - 将按钮的
addTarget移到viewDidLoad中,避免闭包内使用self可能引发的循环引用风险
这样修改后,每次点击按钮只会更新已有的高度约束值,不会新增约束,约束冲突的问题就解决了。
内容的提问来源于stack exchange,提问作者UK4
相关产品推荐
相关产品推荐

