首页 文章

在UITableViewCell中不遵守NSLayoutConstraints

提问于
浏览
2

我有 UITableViewCellUILabelUIImageView . 图像可以是可见的或隐藏的 .

这是我的故事板:

UILabel 的尾随部分有两个约束,一个(a)与 UIImageView 等于8,另一个(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)
}

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

2 回答

  • 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
        }
    }
    

    每当您隐藏icon / iconContainer时,堆栈视图将自行更新并相应地填充空间 .

    If you can't use stack views (首选),你可以试试这个:

    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
        }
    }
    
  • 4

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

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

    @IBOutlet var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint!
    

相关问题