为什么我的 SwiftUI iPhone 应用程序具有摇动撤消功能,可以同时撤消自定义操作和 TextField 更改?

问题描述 投票:0回答:0

我正在构建一个 SwiftUI iPhone 应用程序。我已经通过监听我的主要

View
上的震动并调用
UndoManager
方法来设置一些撤消行为,这些方法有时会注册我自己的动作。

这是主要的一些代码

View

    @Environment(\.undoManager) private var undoManager: UndoManager!
        .onReceive(
            NotificationCenter.default.publisher(for: UIDevice.deviceDidShake),
            perform: handleShake
        )
    private func handleShake(_: Any) {
        if let undoManager = undoManager {
            if undoManager.canUndo {
                undo()
            } else if undoManager.canRedo {
                redo()
            }
        }
    }

一切正常,但我有一个奇怪的情况:

  1. 执行一些注册自定义操作的操作(例如将 TODO 标记为“完成”)
  2. 聚焦
    TextField
    并编辑它
  3. 摇一摇手机

然后发生的是

TextField
中的编辑被撤消并且自定义操作被撤消!

调试打印语句确认只检测到一次震动。

我试过注释掉我的自定义摇动处理,以防 iOS 已经处理摇动以撤消文本字段本身,但事实并非如此。如果没有我的代码将摇动连接到

UndoManager
TextField
编辑不会在摇动时撤消。

另一个有趣的数据点是,如果我没有使用

UndoManager
注册任何自定义撤消操作,然后编辑一个
TextField
,那么
UndoManager.canUndo
就是
false
所以摇动不会撤消任何东西.当
undoManager.undo()
为假时,我什至打电话给
canUndo
,这对TextField没有任何作用!

所以,任何指出我可能做错了什么,或者我不理解撤消在 SwiftUI 中应该如何工作的帮助,将不胜感激!

编辑: 这部分代码也可能相关。

override
正确吗?它是否也应该以某种方式调用
super
实现?

extension UIDevice {
    static let deviceDidShake = Notification.Name("deviceDidShake")
}


extension UIWindow {
    open override func motionEnded(_ motion: UIEvent.EventSubtype, with: UIEvent?) {
        guard motion == .motionShake else { return }
        NotificationCenter.default.post(name: UIDevice.deviceDidShake, object: nil)
    }
}
ios swiftui undo nsundomanager
© www.soinside.com 2019 - 2024. All rights reserved.