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

Swift中设置UILabel的text属性后出现意外删除线异常

UILabel 切换 text 与 attributedText 导致样式异常的原因及解决办法

正常场景

运行以下代码,最终会显示无删除线的红色文本:

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let text = "Hello World"
        let textCount = text.count
        let fullRange = NSRange(location: 0, length: textCount)
        
        var attributedText = NSMutableAttributedString(string: text)
        attributedText.addAttribute(.foregroundColor, value: UIColor.green, range: fullRange)
        attributedText.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: fullRange)
        label.attributedText = attributedText
        
        attributedText = NSMutableAttributedString(string: text)
        attributedText.addAttribute(.foregroundColor, value: UIColor.red, range: fullRange)
        attributedText.removeAttribute(NSAttributedString.Key.strikethroughStyle, range: fullRange)
        label.attributedText = attributedText
    }
}

正常效果


异常场景

如果在中间插入label.text = text操作,最终会显示带删除线的红色文本:

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let text = "Hello World"
        let textCount = text.count
        let fullRange = NSRange(location: 0, length: textCount)
        
        var attributedText = NSMutableAttributedString(string: text)
        attributedText.addAttribute(.foregroundColor, value: UIColor.green, range: fullRange)
        attributedText.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: fullRange)
        label.attributedText = attributedText
        
        // 插入此代码后出现异常
        label.text = text
        
        attributedText = NSMutableAttributedString(string: text)
        attributedText.addAttribute(.foregroundColor, value: UIColor.red, range: fullRange)
        attributedText.removeAttribute(NSAttributedString.Key.strikethroughStyle, range: fullRange)
        label.attributedText = attributedText
    }
}

异常效果


原因分析

这是UILabel内部属性复用机制导致的:

  1. 第一次设置带删除线的attributedText时,UILabel会将删除线样式记录到自身的defaultAttributes(默认属性集合)中。
  2. 当设置label.text = text时,UILabel不会清空之前的默认属性,而是保留已有的样式(比如删除线),仅替换纯文本内容。
  3. 最后设置新的attributedText时,由于你只是移除了删除线属性,并没有明确设置为“无”,UILabel会自动补全默认属性里的删除线样式,导致最终文本带删除线。

简单说:removeAttribute只是从富文本里删掉这个属性,但UILabel会用自己的默认属性补回来;而默认属性已经被之前的操作污染了。


解决办法

方法一:明确设置删除线为“无”

不要用removeAttribute,直接给strikethroughStyle设置NSUnderlineStyle.none.rawValue,强制覆盖默认属性:

attributedText = NSMutableAttributedString(string: text)
attributedText.addAttribute(.foregroundColor, value: UIColor.red, range: fullRange)
// 替换removeAttribute为明确设置none
attributedText.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.none.rawValue, range: fullRange)
label.attributedText = attributedText

方法二:避免混合使用text与attributedText

如果需要控制文本样式,全程使用attributedText更新内容,不要中途切换到text属性,从根源避免默认属性被污染。

方法三:重置UILabel的默认属性(可选)

如果必须切换到text,可以先重置UILabel的属性,比如:

label.text = text
// 重置默认属性中的删除线
label.defaultAttributes.removeValue(forKey: .strikethroughStyle)

不过这种方法需要注意iOS版本兼容性,不如前两种可靠。


内容的提问来源于stack exchange,提问作者Cheok Yan Cheng

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 19:55:16