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

NSAttributedString字体重置及UITextView选中文本格式异常问题咨询

问题解答

1. 设置NSAttributedString的字体后切换选区,字体为何会重置?

这个问题大概率是因为你处理富文本的方式不对:

  • 如果你每次修改字体时,都是基于textView.text(纯字符串)重新创建NSAttributedString,而非基于当前textView.attributedText做增量修改,那之前设置的字体格式会直接丢失。因为text属性会忽略所有富文本格式,相当于把带格式的文本打回原形变成纯文本,重新设置格式时自然覆盖不了之前的修改。
  • 另外,要是你没正确维护textView.textStorage的修改状态——比如直接替换attributedText,而不是用textStorage的beginEditing()/endEditing()接口做编辑——也可能导致文本属性在选区切换时被系统默认行为重置,毕竟UITextView依赖textStorage来维护富文本的持久状态。

2. 选中文本设置粗体/斜体后出现多余空格的原因及修复方案

原因分析

从你给出的代码片段来看,核心问题出在range计算方式错误和未基于现有富文本修改:

  1. 你用textView2.text(纯文本)查找string_to_change的range,但selectedTextWBU是选中文本的字符串——当文本已有格式时,纯文本和富文本内容虽一致,但range(of:)查找可能匹配到错误位置(比如有重复内容时),甚至因字符串匹配偏差,导致修改的range包含额外空格,或替换时不小心插入空格。
  2. 每次基于纯文本创建新的NSAttributedString,会丢失之前所有格式,相当于每次操作都在“重新生成”整个文本,这不仅会丢失格式,还可能因字符串拼接或range计算误差引入多余空格。

修复方案

直接改用textView.selectedRange获取选中区域的准确范围,并且基于当前textView.attributedText(或直接操作textStorage)做增量修改,别碰纯文本的text属性。修正后的代码思路如下:

// 直接获取选中的准确范围,无需通过字符串查找
let selectedRange = textView2.selectedRange
guard selectedRange.length > 0 else { return } // 确保有选中内容

// 操作textStorage是最可靠的方式,它是UITextView富文本的底层存储
textView2.textStorage.beginEditing()

// 获取当前选中区域的字体属性
let currentFont = textView2.textStorage.attribute(.font, at: selectedRange.location, effectiveRange: nil) as? UIFont ?? UIFont.systemFont(ofSize: 17)

// 切换粗体(斜体逻辑完全一致,替换.traitBold为.traitItalic即可)
var newFontDescriptor = currentFont.fontDescriptor
if currentFont.fontDescriptor.symbolicTraits.contains(.traitBold) {
    // 移除粗体
    newFontDescriptor = newFontDescriptor.withSymbolicTraits(newFontDescriptor.symbolicTraits.remove(.traitBold))!
} else {
    // 添加粗体
    newFontDescriptor = newFontDescriptor.withSymbolicTraits(newFontDescriptor.symbolicTraits.union(.traitBold))!
}

let newFont = UIFont(descriptor: newFontDescriptor, size: currentFont.pointSize)
textView2.textStorage.addAttribute(.font, value: newFont, range: selectedRange)

textView2.textStorage.endEditing()

这么做的好处:

  • 用selectedRange完全避免了字符串查找带来的range错误,自然不会出现多余空格。
  • 基于textStorage修改,保留了之前所有富文本格式,不会出现格式丢失问题。
  • 用beginEditing()/endEditing()包裹修改,确保UITextView能正确感知富文本变化,更新UI和内部状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:41:21