iOS 自定义键盘扩展字段中的完整上下文

问题描述 投票:0回答:1

目前,我正在开发自定义 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)
    }

如果我将光标放在文本的中间并从光标之前检索数据,然后将光标向后移动并尝试向前迭代,它只会工作一次。我不明白为什么它不能向前迭代。

ios swift swift-extensions swift-keyboard
1个回答
0
投票

您遇到的问题与 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:) 方法创建要检索的文本范围。这应该确保在检索文本上下文时光标始终位于预期位置。

© www.soinside.com 2019 - 2024. All rights reserved.