1

我遇到的问题UndoManager可能是 iPadOS 错误,但也可能是我的错误。

我有一个简单的测试应用程序。一个按钮执行一个操作,它将 int 增加 1 并向系统注册一个 undo UndoManager。另一个按钮手动调用undoManager.undo(),它撤消最后一个操作,直到撤消堆栈上没有更多操作。并且整个应用程序是系统的第一响应者,因此点击也应该触发 undoManager每按 CMD+ZCMD+Z调用一次。undo()

这是一些代码。

允许成为第一响应者的 UIHostingController 子类:

class FirstResponderHostingController<Content: View>: UIHostingController<Content> {
    override var canBecomeFirstResponder: Bool { true }
}

SceneDelegate,我传入系统撤消管理器的地方:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)

            let model = MyObject(undoManager: window.undoManager)
            let contentView = ContentView(model: model)

            window.rootViewController = FirstResponderHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
    //...
}

还有我的 SwiftUI 视图和相关模型:

class MyObject: ObservableObject {
    var undoManager: UndoManager?
    var state: Int = 0

    init(undoManager: UndoManager? = nil) {
        self.undoManager = undoManager
    }

    func registerAction() {
        state += 1
        undoManager?.registerUndo(withTarget: self, selector: #selector(performUndo), object: nil)
        print("registered action - state is \(state)")
    }

    @objc func performUndo() {
        state -= 1
        print("performUndo called - state is \(state)")
    }

    func undo() {
        print("undo() called")
        undoManager?.undo()
    }
}

struct ContentView: View {
    @ObservedObject var model: MyObject

    var body: some View {
        VStack(spacing: 16) {
            Button(action: {
                self.model.registerAction()
            }) {
                Text("Register an Action")
            }
            Button(action: {
                self.model.undo()
            }) {
                Text("Manual Undo (Not from Keyboard)")
            }
        }
    }
}

例如,如果我点击“注册操作”两次,然后点击“手动撤消”三次,输出就是我所期望的 - 状态增加了两次,然后减少了两次,最后一个 undo() 什么也不做,因为撤消堆栈为空:

registered action - state is 1
registered action - state is 2
undo() called
performUndo called - state is 1
undo() called
performUndo called - state is 0
undo() called

但是,如果我点击“注册操作”两次,然后点击CMD+ZiPad 键盘,我希望状态会增加两次,并且只减少一次,一次调用performUndo,但performUndo仍然被调用两次:

registered action - state is 1
registered action - state is 2
performUndo called - state is 1
performUndo called - state is 0

我是否以某种方式错误地使用了系统 UndoManager,或者这是一个错误?

更新:以上内容适用于 Xcode 11.3.1 和 iPadOS 13.3。使用最新的 Xcode 11.4 beta 2 和 iPadOS 13.4 beta 2,不再发生双重撤销。似乎固定!

4

0 回答 0