ios - UITableViewCell 使用自定义 layoutSubviews() 出现在屏幕上后隐藏部分内容

标签 ios swift uitableview uikit layoutsubviews

我正在为 UITableView 苦苦挣扎。正如您在 this video 中看到的那样在表格 View 的第三部分中,第三个单元格显示不正确。当我像那样出队时会发生这种情况:

let cell = tableView.dequeueReusableCell(withIdentifier: MultipleSelectAnswerSurveyTableViewCellIdentifier, for: indexPath) as! MultipleSelectAnswerSurveyTableViewCell
cell.setup(answer: question.answers?[indexPath.row].value ?? "", isSelected: false, style: style, isLastInSection: indexPath.row == (question.answers?.count ?? 1) - 1)
return cell

Cell 的setup() 方法:

func setup(answer: String, isSelected: Bool, style: Style, isLastInSection: Bool) {
    self.isLastInSection = isLastInSection
    selectionStyle = .none
    backgroundColor = style.survey.singleSelectAnswerTableViewCell.backgroundColor
    answerLabel.textColor = style.survey.singleSelectAnswerTableViewCell.answerLabelColor
    answerLabel.font = style.survey.singleSelectAnswerTableViewCell.answerLabelFont
    answerLabel.text = answer
    addSubview(answerLabel)
    addSubview(selectionIndicator)
    answerLabel.snp.makeConstraints { make in
        make.left.equalTo(8)
        make.centerY.equalTo(selectionIndicator.snp.centerY)
        make.top.equalTo(8)
        make.bottom.equalTo(-8)
        make.right.equalTo(selectionIndicator.snp.left).offset(-8)
    }
    selectionIndicator.snp.makeConstraints { make in
        make.right.equalTo(-8)
        make.top.greaterThanOrEqualTo(8)
        make.bottom.lessThanOrEqualTo(-8)
        make.width.height.equalTo(26)
    }
}

self.isLastInSection 变量在 layoutSubviews() 中使用:

override func layoutSubviews() {
    super.layoutSubviews()
    if isLastInSection {
        roundCorners(corners: [.bottomLeft, .bottomRight], radius: 16.0)
    }
    contentView.layoutIfNeeded()
}

最后 roundCorners():

extension UIView {
    func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        layer.mask = mask
    }
}

当我将 isLastInSection 设置为 false 的单元格出队时,单元格按预期显示 ( related video )。所以我认为问题在于单元格的生命周期以及调用 layoutSubview() 的时间。对于在不同线程中发现的类似问题,我尝试了许多解决方案,但没有一个对我有帮助。 tableView(_:heightForRowAt:) 使第三个单元格正确显示,但第一个单元格的底角是圆的。而且它们的高度都是固定的,这是不可能发生的。 但真正奇怪的是:当我在出列单元格期间打印 isLastInSection 时,调试器返回 false:

(lldb) po indexPath.row == (question.answers?.count ?? 1) - 1 假的

enter image description here

正如您在 Debug View Hierarchy 中看到的那样, View 文本存在,这就是我将问题定义为隐藏部分内容的原因。

Debug View hierarchy

最佳答案

您将单元格出队,并且每次添加 subview 时都不会检查它们是否已经存在,这在回收单元格的情况下会发生。这可能会破坏约束并导致大小调整不正确。

与舍入相同的问题 - 您设置了圆角,但当重复使用的单元格不应被舍入时,您永远不会恢复此行为。

解决此问题的最佳方法是添加额外的检查并仅创建一次 subview :

func setup(answer: String, isSelected: Bool, style: Style, isLastInSection: Bool) {
    if self.subviews.count == 0 {
        // adding subviews etc.
        // code that needs to be performed only once for whole cell's life
    }

    self.isLastInSection = isLastInSection
    // set up content that changes for each cell (like text)
    // for example a code depending on parameters of this method
}

或者,您可以保留一些属性,如 isInitialized 并在开始时检查它。

此外,您的方法 layoutSubviews 必须支持这两种情况:

override func layoutSubviews() {
    super.layoutSubviews()
    if isLastInSection {
        roundCorners(corners: [.bottomLeft, .bottomRight], radius: 16.0)
    } else {
        layer.mask = nil
    }
    contentView.layoutIfNeeded()
}

关于ios - UITableViewCell 使用自定义 layoutSubviews() 出现在屏幕上后隐藏部分内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55191647/

相关文章:

ios - 如何在 swift 中创建一个 UIView 单例?

ios - Tableview 不重新加载自定义附件类型

ios - 如何在 iOS Music App 中实现向上滚动时的 UINavigationBar 动画?

iphone - UITableViewCell背景(图案)

objective-c - UIWebView 委托(delegate)中的 EXC_BAD_ACCESS

ios - for循环中的范围是什么类型?

ios - 从 CoreData 模块获取数据

Swift:覆盖采用 NSInvocation 的初始化程序

ios - Swift - captureOutput 帧提取的颜色总是接近黑色

ios - 不同目标的 default.png(精简版和完整版)