【问题标题】:NSLayoutConstraints is not respected in UITableViewCellNSLayoutConstraints 在 UITableViewCell 中不受尊重
【发布时间】:2019-05-10 18:08:43
【问题描述】:

我有一个UITableViewCell,一个UILabel 和一个UIImageView。图片可以是可见的,也可以是隐藏的。

这是我的故事板:

UILabel 的尾部有两个约束,一个 (a) 等于 8 与 UIImageView,另一个 (b) 大于或等于 8 与单元格的右边距.我保留第一个 (a) 的引用,如果有声音或没有声音,我会激活或停用约束。

这是我的代码:

class MyTableViewCell: UITableViewCell {

    @IBOutlet weak var label: UILabel?
    @IBOutlet weak var icon: UIImageView?
    @IBOutlet weak var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint?

    override func awakeFromNib() {
        super.awakeFromNib()
        icon?.image = UIImage(named: "sound")
    }

    func config(with name: String, hasSound: Bool) {
        label?.text = name
        configSound(hasSound)
    }

    private func configSound(_ hasSound: Bool) {
        icon?.isHidden = !hasSound
        spaceBetweenIconAndLabelConstraint?.isActive = hasSound
    }
}

我有几个带有可见声音图标的单元格,很多没有。以下是特定单元格首次出现时的样子:

当它再次出现在屏幕上时会是什么样子:

我明白问题出在重复使用的单元格上。但我不明白如何防止这种行为。我试着做:

override func prepareForReuse() {
    configSound(true)
}

在重新使用单元格之前重新激活约束,但它不起作用。

【问题讨论】:

  • 单元格是否从有图像变为没有图像(在渲染后),还是一旦单元格由表格设置,它们会保持这种状态直到整个表重新加载了吗?
  • @nard 他们不会即时更改。如果一个单元格有一张图片,它就会一直有,或者永远不会有。
  • 然后只需创建两种类型的单元格,有图像和没有图像,并让数据源确定哪一个出列。当表格变大并且滚动速度很快时,在可重用单元格中有条件地实施约束可能会产生令人讨厌的结果 - 使单元格尽可能保持基本以优化表格性能。
  • 问题是我简化了帖子的代码,但它做了更多的事情,我不喜欢代码重复,我不知道如何从具有 IBOutlet 的类继承(或如果这是可能的)。

标签: ios swift uitableview nslayoutconstraint prepareforreuse


【解决方案1】:

我认为问题在于您使用weak 引用作为约束。在这种情况下,只要它的isActive 属性第一次设置为false,约束就会被删除。从那以后它是nil 并且不能被重新激活。

解决方案:通过删除 weak 关键字来使用强引用。

@IBOutlet var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint!

【讨论】:

  • 非常感谢,除了解决问题,我还了解到将弱约束设置为 false 会使其为零! :)
【解决方案2】:

有不止两种方法可以做到这一点。如果您的目标是 iOS 9+,我强烈建议您使用堆栈视图。它们完全符合您的需求,无需手动添加/删除/激活/停用约束。

用户界面将如下所示:

stack view setup

水平堆栈视图(8 到前导,8 到尾随,间距等于 8) 里面: 1. 在左侧标签上 2.在右图标图像视图上(可选地包裹在iconContainer视图中,或者只是设置aspectFit)

更新代码:

class MyTableViewCellWithStackView: UITableViewCell {

    @IBOutlet weak var label: UILabel?
    @IBOutlet weak var iconContainer: UIView?

    func config(with name: String, hasSound: Bool) {
        label?.text = name
        iconContainer?.isHidden = !hasSound
    }
}

每当您隐藏图标/图标容器时,堆栈视图都会自行更新并相应地填充空间。

如果你不能使用堆栈视图(首选),你可以试试这个:

class MyTableViewCell: UITableViewCell {

    @IBOutlet weak var label: UILabel?
    @IBOutlet weak var icon: UIImageView?
    @IBOutlet weak var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint?

    override func awakeFromNib() {
        super.awakeFromNib()
        icon?.image = UIImage(named: "sound")
    }

    func config(with name: String, hasSound: Bool) {
        label?.text = name
        configSound(hasSound)
    }

    private func configSound(_ hasSound: Bool) {
        icon?.isHidden = !hasSound
        guard hasSound else {
            spaceBetweenIconAndLabelConstraint?.isActive = false
            return
        }
        guard let icon = icon, let label = label else { return }

        let constraint = label.rightAnchor
                                .constraint(equalTo: icon.leftAnchor, constant: 8)
        constraint.isActive = true
        spaceBetweenIconAndLabelConstraint = constraint
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 2020-02-21
    • 1970-01-01
    • 2020-05-27
    • 2012-07-25
    • 2022-12-21
    • 1970-01-01
    相关资源
    最近更新 更多