NSAttributedString字体重置及UITextView选中文本格式异常问题咨询
问题解答
1. 设置NSAttributedString的字体后切换选区,字体为何会重置?
这个问题大概率是因为你处理富文本的方式不对:
- 如果你每次修改字体时,都是基于
textView.text(纯字符串)重新创建NSAttributedString,而非基于当前textView.attributedText做增量修改,那之前设置的字体格式会直接丢失。因为text属性会忽略所有富文本格式,相当于把带格式的文本打回原形变成纯文本,重新设置格式时自然覆盖不了之前的修改。 - 另外,要是你没正确维护
textView.textStorage的修改状态——比如直接替换attributedText,而不是用textStorage的beginEditing()/endEditing()接口做编辑——也可能导致文本属性在选区切换时被系统默认行为重置,毕竟UITextView依赖textStorage来维护富文本的持久状态。
2. 选中文本设置粗体/斜体后出现多余空格的原因及修复方案
原因分析
从你给出的代码片段来看,核心问题出在range计算方式错误和未基于现有富文本修改:
- 你用
textView2.text(纯文本)查找string_to_change的range,但selectedTextWBU是选中文本的字符串——当文本已有格式时,纯文本和富文本内容虽一致,但range(of:)查找可能匹配到错误位置(比如有重复内容时),甚至因字符串匹配偏差,导致修改的range包含额外空格,或替换时不小心插入空格。 - 每次基于纯文本创建新的
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
相关产品推荐
相关产品推荐

