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内部属性复用机制导致的:
- 第一次设置带删除线的
attributedText时,UILabel会将删除线样式记录到自身的defaultAttributes(默认属性集合)中。 - 当设置
label.text = text时,UILabel不会清空之前的默认属性,而是保留已有的样式(比如删除线),仅替换纯文本内容。 - 最后设置新的
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
相关产品推荐
相关产品推荐

