You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UITableViewCell复用后无法重置UILabel attributedText消除删除线

解决UITableViewCell复用后UILabel删除线残留的问题

这个问题我太熟悉了——UITableViewCell复用机制下,标签的富文本属性经常会出现“顽固残留”,尤其是删除线这种样式。咱们一步步拆解问题,找到彻底解决的办法。

问题根源

你代码里的核心陷阱在于:混用了text和attributedText两种文本设置方式。当你为拒付交易设置带删除线的富文本后,非拒付场景直接设置普通text,这时候UILabel并不会完全清除之前的富文本属性——设置text本质是生成一个默认样式的富文本,但会继承之前残留的属性(比如你没显式覆盖的字体、颜色),导致删除线偷偷保留下来。另外,之前的重置逻辑不够彻底,没有在系统指定的复用时机做清理。

正确的解决方案

我推荐两种互补的方法,双管齐下确保样式完全可控:

1. 重写prepareForReuse做彻底重置(必做)

在TimelineTableViewCell里重写这个方法,这是系统在单元格即将被复用前的“官方清理时机”,比在didSet里做重置更可靠:

override func prepareForReuse() {
    super.prepareForReuse()
    // 彻底清空标签的所有文本相关属性
    transactionDescriptionLabel.text = nil
    transactionDescriptionLabel.attributedText = NSAttributedString(string: "")
    transactionValueLabel.text = nil
    transactionValueLabel.attributedText = NSAttributedString(string: "")
    // 重置数据源引用,避免残留
    transactionData = nil
}

为什么要设置空的NSAttributedString?因为只设置nil有时候无法完全清除富文本的属性缓存,显式设置空文本能确保标签回到“干净”的初始状态。

2. 统一用attributedText设置文本(避免混用)

在transactionData的didSet里,不管是不是拒付交易,都用attributedText来设置,彻底抛弃text设置方式。这样能完全掌控标签的样式,避免冲突:

var transactionData: TimelineResponseModel! {
    didSet {
        guard transactionData != nil else { return }
        
        let descText = transactionData.description
        let valueText = Formatter.currency.string(for: transactionData.balance) ?? ""
        
        if transactionData.isChargeback {
            // 拒付场景:设置带删除线的富文本
            transactionDescriptionLabel.attributedText = descText.strikedThrough(with: .preferredFont(forTextStyle: .footnote))
            transactionValueLabel.attributedText = valueText.strikedThrough(with: UIFont.preferredFont(forTextStyle: .caption1).bold())
        } else {
            // 非拒付场景:设置不带额外样式的富文本,明确指定字体和颜色
            let descAttrs: [NSAttributedString.Key: Any] = [
                .font: UIFont.preferredFont(forTextStyle: .footnote),
                .foregroundColor: UIColor.activeText()
            ]
            transactionDescriptionLabel.attributedText = NSAttributedString(string: descText, attributes: descAttrs)
            
            let valueAttrs: [NSAttributedString.Key: Any] = [
                .font: UIFont.preferredFont(forTextStyle: .caption1).bold(),
                .foregroundColor: UIColor.activeText()
            ]
            transactionValueLabel.attributedText = NSAttributedString(string: valueText, attributes: valueAttrs)
        }
    }
}

3. 优化你的strikedThrough扩展(可选但更严谨)

给扩展加上默认的字体和颜色参数,避免继承旧标签的残留属性:

extension String {
    func strikedThrough(with font: UIFont, color: UIColor = .activeText()) -> NSAttributedString {
        let attributes: [NSAttributedString.Key: Any] = [
            .strikethroughStyle: NSUnderlineStyle.single.rawValue,
            .font: font,
            .foregroundColor: color
        ]
        return NSAttributedString(string: self, attributes: attributes)
    }
}

为什么之前的尝试无效?

  • 你之前的prepareForReuse可能只设置了text和attributedText为nil,没有显式设置空的富文本,无法彻底清除属性缓存;
  • 你添加的else分支可能还是用了text设置,导致和之前的attributedText设置产生冲突,样式残留。

内容的提问来源于stack exchange,提问作者Marcos Tanaka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:29:02