首页 > 解决方案 > 使用 SwiftUI TextEditor 撤消/重做文本输入

问题描述

诚然,这是一个广泛的问题,但是在使用 SwiftUI TextEditor 控件时是否可以撤消或重做文本输入(通过 iOS 的 UndoManager?)?我到处找,找不到任何专注于这个工作流程组合的资源(SwiftUI + TextEditor + UndoManager)。我想知道 TextEditor 的相对不成熟,要么这根本不可能,要么需要一些管道工作来促进。任何指导将不胜感激!

标签: swiftswiftuitext-editorundo-redonsundomanager

解决方案


诚然,这有点 hack 并且不是 SwiftUI-y,但它确实有效。基本上在你的 UITextView:UIViewRepresentable 中声明一个绑定到 UndoManager。您的 UIViewRepresentable 会将绑定设置为 UITextView 提供的 UndoManager。然后你的父视图可以访问内部的 UndoManager。这是一些示例代码。尽管此处未显示,但重做也可以正常工作。

struct MyTextView: UIViewRepresentable {

    /// The underlying UITextView. This is a binding so that a parent view can access it. You do not assign this value. It is created automatically.
    @Binding var undoManager: UndoManager?

    func makeUIView(context: Context) -> UITextView {
        let uiTextView = UITextView()

        // Expose the UndoManager to the caller. This is performed asynchronously to avoid modifying the view at an inappropriate time.
        DispatchQueue.main.async {
            undoManager = uiTextView.undoManager
        }

        return uiTextView
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
    }

}

struct ContentView: View {

    /// The underlying UndoManager. Even though it looks like we are creating one here, ultimately, MyTextView will set it to its internal UndoManager.
    @State private var undoManager: UndoManager? = UndoManager()

    var body: some View {
        NavigationView {
            MyTextView(undoManager: $undoManager)
            .toolbar {
                ToolbarItemGroup(placement: .navigationBarTrailing) {
                    Button {
                        undoManager?.undo()
                    } label: {
                        Image(systemName: "arrow.uturn.left.circle")
                    }
                    Button {
                        undoManager?.redo()
                    } label: {
                        Image(systemName: "arrow.uturn.right.circle")
                    }
                }
            }
        }
    }
}

推荐阅读