【问题标题】:Implementing undo and redo in a UITextView with attributedText使用属性文本在 UITextView 中实现撤消和重做
【发布时间】:2018-11-04 20:07:12
【问题描述】:

我正在尝试将 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()
}

【问题讨论】:

  • 您能否包含代码以显示您在何处注册撤消操作?
  • 请确保IBAction 已连接到您的UIButton。我已经测试了您的代码是否适合我。
  • @sanch 是的,这是问题所在,但不确定如何注册所有属性等。@AbecedarioPoint 我接受了您的编辑,但实际上函数是通过编程方式调用的,因此不需要@IBAction跨度>
  • 我认为这将回答您的大部分问题。 stackoverflow.com/a/32596899
  • @AbecedarioPoint 您的编辑不正确。程序化 UI 不需要 IBAction,它的字面意思是 InterfaceBuilderAction。 Op 设置了 objc 句柄是正确的,因为 selector 是一个 objc 方法并且类型推断不再隐含在 swift 4 中

标签: swift uitextview nsattributedstring undo redo


【解决方案1】:

这里有一些示例代码用于处理 UITextView 的撤消/重做。不要忘记在最初和每次更改文本后更新您的撤消/重做按钮状态。

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()            
    }
}

显然,您需要在故事板中连接动作/出口和文本视图的代理出口

【讨论】:

  • 谢谢!这绝对是最好的解决方案。我已经用我想要的特性/怪癖从头开始实现了我自己的版本,但我希望这对任何想要在UITextView上实现撤消/重做的人有用@
【解决方案2】:

这不是解决 OP 问题的方法,而是一种粗略的替代方案

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

【讨论】:

  • 无需自己编写 - 这是“免费”的。每个UIResponder 都有一个可选的undoManager,它处理堆栈的推入/弹出。
  • @AshleyMills,您当然是正确的。我在答案中添加了一个限定声明。
猜你喜欢
  • 2011-05-03
  • 2012-06-02
  • 2011-03-10
  • 2014-10-11
  • 2011-11-14
  • 2016-02-18
  • 1970-01-01
  • 2021-06-04
  • 1970-01-01
相关资源
最近更新 更多