如何为NSMutableAttributedString添加粗体并保留其他字体特征?
问题核心原因
你当前的实现直接使用全局统一的normalFont生成粗体字体,覆盖选中范围的.font属性,会丢失选中范围内每段文本原本的字体特征(比如斜体、自定义字号、特殊字族)。下划线属于独立的富文本属性,本身不会被字体修改操作影响,问题根源是字体替换逻辑没有基于原有字体做增量修改。
正确实现逻辑
- 不直接使用全局预设字体生成粗体,逐段读取选中范围内每段文本已有的字体属性
- 基于每段原有字体的特征集合,追加
.traitBold粗体特征,不覆盖已有的斜体等其他特征 - 用追加特征后的字体描述生成新字体,仅更新对应片段的字体属性,保留所有原有字体相关配置
可直接使用的修正代码
let text = NSMutableAttributedString(attributedString: textView.attributedText) let selectedRange = textView.selectedRange text.enumerateAttribute(.font, in: selectedRange, options: []) { fontAttr, range, _ in // 优先取当前段原有字体,无字体属性时降级到全局默认字体 let originalFont = fontAttr as? UIFont ?? AppearanceManager.shared.font ?? .systemFont(ofSize: 14) // 在原有字体特征基础上追加粗体,不覆盖斜体等已有特征 var traits = originalFont.fontDescriptor.symbolicTraits traits.formUnion(.traitBold) guard let boldFontDescriptor = originalFont.fontDescriptor.withSymbolicTraits(traits) else { return } let targetBoldFont = UIFont(descriptor: boldFontDescriptor, size: originalFont.pointSize) text.addAttribute(.font, value: targetBoldFont, range: range) } textView.attributedText = text
补充说明
- 下划线、文字颜色、删除线、字间距等非字体类富文本属性不会被上述逻辑修改,会完整保留
- 原有字体的斜体特征、自定义字族、局部不同字号等字体相关配置都会被保留,仅额外增加粗体效果
- 如果需要实现取消粗体的功能,仅需将代码中
traits.formUnion(.traitBold)替换为traits.remove(.traitBold)即可,逻辑通用 - 禁止直接给整个选中范围设置统一字体值,否则会抹掉选区内所有局部字体差异
内容的提问来源于stack exchange,提问作者Michael Sebsbe
相关产品推荐
相关产品推荐

