目前,我正在开发自定义 Swift 键盘并使用 Keyboard Kit 框架。
我研究了各种解决方案,这个是最好的
但是在我为 Swift 5 实现此代码后,当我将光标放在文本末尾时它可以工作。
代码:
let readerQueue = DispatchQueue(label: "com.customKeyboard.reader.test")
func foo() {
readerQueue.async {
self.keyboardService.fullDocumentContext()
}
}
func fullDocumentContext() {
guard let textProxy else { return }
var startingOffset = 0
var context = ""
while let previeosContext = textProxy.documentContextBeforeInput, !previeosContext.isEmpty {
context = previeosContext + context
startingOffset += previeosContext.count
textProxy.adjustTextPosition(byCharacterOffset: -previeosContext.count)
Thread.sleep(forTimeInterval: 0.01)
}
textProxy.adjustTextPosition(byCharacterOffset: context.count)
Thread.sleep(forTimeInterval: 0.01)
while let nextContext = textProxy.documentContextAfterInput, !nextContext.isEmpty {
context += nextContext
textProxy.adjustTextPosition(byCharacterOffset: nextContext.count)
Thread.sleep(forTimeInterval: 0.01)
}
print(context)
}
如果我将光标放在文本的中间并从光标之前检索数据,然后将光标向后移动并尝试向前迭代,它只会工作一次。我不明白为什么它不能向前迭代。
您遇到的问题与 adjustTextPosition(byCharacterOffset:) 方法在 UITextInput 协议中的工作方式有关。
根据文档,此方法将文本输入对象中的插入点移动给定的偏移量。但是,它并不能保证新的插入点会在预期的位置,因为它取决于底层文本引擎的实现。
在您的 fullDocumentContext() 函数中,您调用 adjustTextPosition(byCharacterOffset:) 来前后移动插入点。这可能会导致插入点的位置与预期位置不同,尤其是在您使用非标准键盘的情况下。
要解决这个问题,可以使用UITextInput协议的selectedTextRange属性获取当前光标位置,然后使用该位置调整光标前后的文本位置。这是使用 selectedTextRange 属性的 fullDocumentContext() 函数的更新版本:
func fullDocumentContext() {
guard let textProxy else { return }
var startingOffset = 0
var context = ""
if let selectedRange = textProxy.selectedTextRange {
if let start = textProxy.position(from: selectedRange.start, offset: -100),
let range = textProxy.textRange(from: start, to: selectedRange.start),
let previeosContext = textProxy.text(in: range)
{
context = previeosContext + context
startingOffset += previeosContext.count
}
if let end = textProxy.position(from: selectedRange.start, offset: 100),
let range = textProxy.textRange(from: selectedRange.start, to: end),
let nextContext = textProxy.text(in: range)
{
context += nextContext
}
print(context)
}
}
在这个更新的函数中,我们使用 selectedTextRange 属性检索当前光标位置。然后我们使用这个位置来获取光标前后的文本,使用 textRange(from: to:) 方法创建要检索的文本范围。这应该确保在检索文本上下文时光标始终位于预期位置。