使用 attributedText 在 UITextView 中实现撤消和重做

Implementing undo and redo in a UITextView with attributedText

我正在尝试将 undoredo 功能添加到我的 UITextView 实现中。我使用的是 attributedText 而不仅仅是 UITextViewtext 属性。我试过使用 undoManager 中的函数调用,如 Apple documentation 中引用的那样,但似乎没有任何反应。令我惊讶的是,我无法通过谷歌搜索找到有关该主题的任何内容。之前有没有人遇到过这个问题/在 UITextViewattributedText 上实施撤消和重做/知道如何解决这个问题?

示例代码

textView.attributedText = NSMutableAttributedString(string: "SOME TEXT")

@objc func undo(_ sender: UIButton) {
    textView.undoManager?.undo()
}

@objc func redo(_ sender: UIButton) {
    textView.undoManager?.redo()
}

这不是 OP 问题的解决方案,而是一种原始替代方案

在我认为您可以通过结合 UITextField 委托回调实现堆栈数据结构来获得它之前,我还没有处理过这个问题 textViewDidFinishEditing(textField: UITextField)。这个想法是,对于用户对文本字段所做的每一次更改,您都将当前属性字符串放入堆栈中。 undo 功能通过将按钮连接到您的堆栈并弹出最近的属性字符串并相应地设置文本字段属性字符串 属性 来发挥作用。

这里有一些示例代码可以处理 undo/redo 的 UITextView。不要忘记更新 undo/redo 按钮的初始状态和每次更改文本后的状态。

class ViewController: UIViewController {

    @IBOutlet weak var textView: UITextView!
    @IBOutlet weak var undoButton: UIButton!
    @IBOutlet weak var redoButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        updateUndoButtons()
    }

    @IBAction func undo(_ sender: Any) {
        textView.undoManager?.undo()
        updateUndoButtons()
    }

    @IBAction func redo(_ sender: Any) {
        textView.undoManager?.redo()
        updateUndoButtons()
    }

    func updateUndoButtons() {
        undoButton.isEnabled = textView.undoManager?.canUndo ?? false
        redoButton.isEnabled = textView.undoManager?.canRedo ?? false
    }
}        

extension ViewController: UITextViewDelegate {

    func textViewDidChange(_ textView: UITextView) {
        updateUndoButtons()            
    }
}

显然,您需要在情节提要中连接 actions/outlets 和文本视图的委托出口