Клавиатура iPadOS CMD + Z дважды вызывает селектор отмены UndoManager? - PullRequest
0 голосов
/ 20 февраля 2020

У меня проблема с UndoManager, которая может быть ошибкой iPadOS, но также может быть моей ошибкой.

У меня есть простое тестовое приложение. Одна кнопка выполняет действие, которое увеличивает int на 1 и регистрирует отмену в системе UndoManager. Другая кнопка вручную вызывает undoManager.undo(), которая отменяет последнее действие до тех пор, пока не останется больше никаких действий в стеке отмены. И в целом приложение является первым респондентом системы, поэтому нажатие CMD+Z также должно инициировать вызов undoManager undo() один раз за CMD + Z, нажмите .

Вот некоторый код.

Подкласс 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)")
            }
        }
    }
}

Так, например, если я дважды коснусь «Зарегистрировать действие», а затем трижды «Отмена вручную», результат будет таким, как я ожидаю - состояние было увеличено в два раза, а затем уменьшено в два раза, и последняя отмена () ничего не делает, потому что стек отмены пуст:

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+Z на клавиатуре iPad, я ожидаю, что состояние увеличиваться в два раза и уменьшаться только один раз, с одним вызовом 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, двойная отмена больше не происходит. Кажется исправлено!

...