iOS自定义键盘Swift编程实现特定文本高亮功能求助
解决方案
在iOS键盘扩展中,要编程选中现有文本,不能直接用setMarkedText(它的作用是插入带标记的新文本),需要根据系统版本选择不同的实现方式:
iOS 15+ 原生API直接选中
iOS 15及以上,UITextDocumentProxy新增了setSelectedRange(_:)方法,可以直接设置输入框的文本选中范围,完全不会修改原有内容:
// 1. 获取光标前后的文本,拼接成完整内容 let beforeText = textDocumentProxy.documentContextBeforeInput ?? "" let afterText = textDocumentProxy.documentContextAfterInput ?? "" let fullText = beforeText + afterText // 2. 定位目标单词的范围(这里以"targetWord"为例) guard let targetRange = fullText.range(of: "targetWord") else { return } let startIndex = fullText.distance(from: fullText.startIndex, to: targetRange.lowerBound) let length = fullText.distance(from: targetRange.lowerBound, to: targetRange.upperBound) // 3. 计算选中范围并设置 if #available(iOS 15.0, *) { let selectedRange = NSRange(location: startIndex, length: length) textDocumentProxy.setSelectedRange(selectedRange) }
iOS 15以下 兼容方案
对于低版本系统,只能通过「删除目标文本后插入带标记的相同文本」的方式实现选中效果(内容不会改变,只是触发高亮):
1. 扩展UITextDocumentProxy实现批量删除
extension UITextDocumentProxy { func deleteBackward(times: Int) { for _ in 0..<times { deleteBackward() } } }
2. 实现选中逻辑
let beforeText = textDocumentProxy.documentContextBeforeInput ?? "" let afterText = textDocumentProxy.documentContextAfterInput ?? "" let fullText = beforeText + afterText guard let targetRange = fullText.range(of: "targetWord") else { return } let targetText = String(fullText[targetRange]) let length = targetText.count // 计算光标到目标文本起始位置的偏移量 let startOffset = fullText.distance(from: fullText.startIndex, to: targetRange.lowerBound) - beforeText.count // 移动光标到目标起始位置,删除目标文本,再插入带标记的原文本 textDocumentProxy.adjustTextPosition(byCharacterOffset: startOffset) textDocumentProxy.deleteBackward(times: length) textDocumentProxy.setMarkedText(targetText, selectedRange: NSRange(location: 0, length: length))
注意事项
- 无法直接获取输入框的全部文本,只能通过
documentContextBeforeInput和documentContextAfterInput拼接,所以要确保目标单词在这两个上下文的覆盖范围内。 - 如果目标单词跨光标位置(一部分在before,一部分在after),上述代码依然可以正常处理。
内容的提问来源于stack exchange,提问作者im07
相关产品推荐
相关产品推荐

