在具有 IME 支持的 UITextView 中实现撤消/重做功能

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

目前,我们正在

UITextView
中实现撤消/重做功能。

但是,我们不能在

UndoManager
中使用内置的
UITextView
,因为我们在
UITextView
中有多个
UICollectionView
实例。

由于 UICollectionView 回收

UITextView
实例,因此相同的
UITextView
可能会在不同的行中重复使用,从而使内置
UndoManager
不可靠。

shouldChangeTextIn
中的
UITextViewDelegate
方法是正确实现撤消/重做功能的关键。这是我们的实施示例:

extension ChecklistCell: UITextViewDelegate {
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        // Get the current text
        let s = textView.text ?? ""
        
        // Get the starting position of the change
        let start = range.location
        
        // Get the number of characters that will be replaced
        let count = range.length
        
        // Get the number of characters that will be added
        let after = text.count
        
        print(">>>> The current text = \"\(s)\"")
        print(">>>> The starting position of the change = \(start)")
        print(">>>> The number of characters that will be replaced = \(count)")
        print(">>>> The number of characters that will be added = \(after)")
        print(">>>>")
        
        if let delegate = delegate, let checklistId = checklistId, let index = delegate.checklistIdToIndex(checklistId) {
            delegate.attachTextAction(s: s, start: start, count: count, after: after, index: index)
        }
        
        return true
    }
}

这就是它的样子。

https://www.facebook.com/wenotecolor/videos/2174891132886868 - 撤消/重做在英语中效果很好

UITextViewDelegate背后的工作场景

enter image description here


但是,此实现不适用于使用 IME 的非英语输入。使用 IME 时,在产生最终输入之前有一个中间输入。例如,输入“wo”(中间输入)会生成“我”(最终输入)。目前,

UITextViewDelegate
同时捕获“我”和“我”。

UITextViewDelegate
捕捉“我”和“我”

enter image description here

有没有办法忽略IME的中间输入而只考虑最终输入?


在Android中,我们使用TextWatcher中的

beforeTextChanged
方法来无缝忽略IME的中间输入,只考虑最终输入。您可以在此处看到它的实际效果

Android 只捕获“我”

enter image description here

iOS 中是否有等效的方法来忽略 IME 的中间输入并仅考虑最终输入?

ios swift uikit uitextview uitextviewdelegate
1个回答
0
投票

由于 IME 分别注册每个字符,因此我建议简单地区分英语和普通话字符,并仅注册后者。

extension ChecklistCell: UITextViewDelegate {
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        // Check if the replacement text contains only Mandarin characters
        let isMandarin = textView.text.range(of: "\\p{Script=Han}", options: .regularExpression) != nil
        
        if isMandarin {
            let s = textView.text ?? ""
    
    // Get the starting position of the change
    let start = range.location
    
    // Get the number of characters that will be replaced
    let count = range.length
    
    // Get the number of characters that will be added
    let after = text.count
    
    print(">>>> The current text = \"\(s)\"")
    print(">>>> The starting position of the change = \(start)")
    print(">>>> The number of characters that will be replaced = \(count)")
    print(">>>> The number of characters that will be added = \(after)")
    print(">>>>")
    
    if let delegate = delegate, let checklistId = checklistId, let index = delegate.checklistIdToIndex(checklistId) {
        delegate.attachTextAction(s: s, start: start, count: count, after: after, index: index)
    }
    
    return true
}
}

对于英文版应用程序,可以轻松禁用此功能。

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