重新扩展表视图时 Swift 约束被破坏

发布于 2025-01-13 10:08:54 字数 2242 浏览 1 评论 0原文

所以我有一个包含部分和行的 2 深度表视图。当我第一次展开表视图时,一切都已经很好了,但是如果我将其展开第二次、第三次……次或在部分展开时滚动,那么行部分的左侧约束就会被打破,因为更多详细信息请参见下图:

请参阅此了解详细信息

这是我第三次扩展部分。正如您所看到的,有 2 行打破了左约束。这是我的代码:

func configureCell(data: FirstDepth) {
    self.firstDepthData = data
    self.firstDepthLabel.text = data.name
    self.firstDepthLabel.centerY(inView: contentView, leftAnchor: contentView.leftAnchor, paddingLeft: 20)
}

func configureSecondCell(data: SecondDepth) {
    self.secondDepthData = data
    self.firstDepthLabel.text = data.name
    self.firstDepthLabel.centerY(inView: contentView, leftAnchor: contentView.leftAnchor, paddingLeft: 50)
}

所以表视图将为部分调用configureCell,为行调用configureSecondCell,我读过这可能是因为重新初始化约束,但如何只更新常量?

如果需要,这是我的表格视图单元格的代码:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: CellFirstDepth.id, for: indexPath) as! CellFirstDepth
    
    if let firstDepthData = self.firstDepthData {
        if indexPath.row == 0 {
            // Call Cell for sections
            cell.configureCell(data: firstDepthData[indexPath.section])
        } else {
            // Call Cell for rows
            cell.configureSecondCell(data: firstDepthData[indexPath.section].child[indexPath.row - 1])
        }
    }
    return cell
}

这是我的 centerY 函数,只是使元素以 Y 轴为中心,并向左/右添加锚点的代码:

func centerY(inView view: UIView, leftAnchor: NSLayoutXAxisAnchor? = nil, rightAnchor: NSLayoutXAxisAnchor? = nil, paddingLeft: CGFloat? = nil, paddingRight: CGFloat? = nil, constant: CGFloat? = 0) {
    translatesAutoresizingMaskIntoConstraints = false
    
    centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: constant!).isActive = true
    
    if let leftAnchor = leftAnchor, let paddingLeft = paddingLeft {
        self.leftAnchor.constraint(equalTo: leftAnchor, constant: paddingLeft).isActive = true
    } else if let rightAnchor = rightAnchor, let paddingRight = paddingRight {
        self.rightAnchor.constraint(equalTo: rightAnchor, constant: -paddingRight).isActive = true
    }
}

So I have a 2 depth table view with sections and rows. When I expand the table view for the first time, everything's already good, but if I expand it for the 2nd, 3rd, .... times or scrolling when the sections expanded, then the left constraint for the rows sections is broken, for more details please see the image below:

Please see this for details

It's my 3rd time I expanding the sections. And as you can see there're 2 rows that have broken left constraint. Here's my code:

func configureCell(data: FirstDepth) {
    self.firstDepthData = data
    self.firstDepthLabel.text = data.name
    self.firstDepthLabel.centerY(inView: contentView, leftAnchor: contentView.leftAnchor, paddingLeft: 20)
}

func configureSecondCell(data: SecondDepth) {
    self.secondDepthData = data
    self.firstDepthLabel.text = data.name
    self.firstDepthLabel.centerY(inView: contentView, leftAnchor: contentView.leftAnchor, paddingLeft: 50)
}

So the table view will call configureCell for the sections, and configureSecondCell for the rows, I've read maybe this is because of re-initialize the constraints, but how to only update the constant?

If needed, here's my code for the table view cell:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: CellFirstDepth.id, for: indexPath) as! CellFirstDepth
    
    if let firstDepthData = self.firstDepthData {
        if indexPath.row == 0 {
            // Call Cell for sections
            cell.configureCell(data: firstDepthData[indexPath.section])
        } else {
            // Call Cell for rows
            cell.configureSecondCell(data: firstDepthData[indexPath.section].child[indexPath.row - 1])
        }
    }
    return cell
}

And this is my centerY function, just a code to make the element center to Y axis, and add anchor to left/right:

func centerY(inView view: UIView, leftAnchor: NSLayoutXAxisAnchor? = nil, rightAnchor: NSLayoutXAxisAnchor? = nil, paddingLeft: CGFloat? = nil, paddingRight: CGFloat? = nil, constant: CGFloat? = 0) {
    translatesAutoresizingMaskIntoConstraints = false
    
    centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: constant!).isActive = true
    
    if let leftAnchor = leftAnchor, let paddingLeft = paddingLeft {
        self.leftAnchor.constraint(equalTo: leftAnchor, constant: paddingLeft).isActive = true
    } else if let rightAnchor = rightAnchor, let paddingRight = paddingRight {
        self.rightAnchor.constraint(equalTo: rightAnchor, constant: -paddingRight).isActive = true
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自在安然 2025-01-20 10:08:54

您还没有向我们展示您的 .centerY(...) 函数的作用,但对问题的猜测相当安全。

看起来您正在添加常量为 20.leftAnchor 约束,然后单元格会被重用,并且您将添加另一个 strong> .leftAnchor 约束,常量为 50

您需要编辑单元格代码以使用单个约束,并更新其.constant属性,而不是添加多个约束。


编辑

通过一些搜索,您可以找到许多完整的示例,但这里是总体思路。

在您的单元类中,添加此 var 属性:

var labelLeftConstraint: NSLayoutConstraint!

然后,在您的单元类初始化中,创建该约束:

labelLeftConstraint = self.firstDepthLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 0)
labelLeftConstraint.isActive = true

并且,像这样更改您的 configure 函数:

func configureCell(data: FirstDepth) {
    self.firstDepthData = data
    self.firstDepthLabel.text = data.name
    labelLeftConstraint.constant = 20
    //self.firstDepthLabel.centerY(inView: contentView, leftAnchor: contentView.leftAnchor, paddingLeft: 20)
}

func configureSecondCell(data: SecondDepth) {
    self.secondDepthData = data
    self.firstDepthLabel.text = data.name
    labelLeftConstraint.constant = 50
    //self.firstDepthLabel.centerY(inView: contentView, leftAnchor: contentView.leftAnchor, paddingLeft: 50)
}

现在您将只有一个单个 strong> 约束,并且您的代码将设置其 .constant 而不是一遍又一遍地创建它(这就是导致问题的原因)。

You haven't shown us what your .centerY(...) function does, but pretty safe guess as to the problem.

It looks like you are adding a .leftAnchor constraint with a constant of 20, and then the cell get's reused and you're adding another .leftAnchor constraint with a constant of 50.

You need to edit your cell code to use a single constraint, and update its .constant property, instead of adding multiple constraints.


Edit

With a little searching, you can find many complete examples, but here's the general idea.

In your cell class, add this var property:

var labelLeftConstraint: NSLayoutConstraint!

Then, in your cell class initialization, create that constraint:

labelLeftConstraint = self.firstDepthLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 0)
labelLeftConstraint.isActive = true

And, change your configure funcs like this:

func configureCell(data: FirstDepth) {
    self.firstDepthData = data
    self.firstDepthLabel.text = data.name
    labelLeftConstraint.constant = 20
    //self.firstDepthLabel.centerY(inView: contentView, leftAnchor: contentView.leftAnchor, paddingLeft: 20)
}

func configureSecondCell(data: SecondDepth) {
    self.secondDepthData = data
    self.firstDepthLabel.text = data.name
    labelLeftConstraint.constant = 50
    //self.firstDepthLabel.centerY(inView: contentView, leftAnchor: contentView.leftAnchor, paddingLeft: 50)
}

Now you will have only a single constraint, and your code will be setting its .constant instead of creating it over and over (which is what causes the problem).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文