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
相关产品推荐
相关产品推荐

