目前,我们正在
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 - 撤消/重做在英语中效果很好
但是,此实现不适用于使用 IME 的非英语输入。使用 IME 时,在产生最终输入之前有一个中间输入。例如,输入“wo”(中间输入)会生成“我”(最终输入)。目前,
UITextViewDelegate
同时捕获“我”和“我”。
UITextViewDelegate
捕捉“我”和“我”有没有办法忽略IME的中间输入而只考虑最终输入?
在Android中,我们使用TextWatcher
中的
beforeTextChanged方法来无缝忽略IME的中间输入,只考虑最终输入。您可以在此处看到它的实际效果
iOS 中是否有等效的方法来忽略 IME 的中间输入并仅考虑最终输入?
由于 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
}
}
对于英文版应用程序,可以轻松禁用此功能。