Is it possible to override UITextView
's handling of cmd + z
and cmd + shift + z
?
I've tried to
keyCommand
property, but the selectors are never called..undoManager
, this doesn't help eitherclass CustomTextView: UITextView {
override var keyCommands: [UIKeyCommand]? {
[
// cmd + z (doesn't work)
UIKeyCommand(input: "z", modifierFlags: [.command], action: #selector(undo)),
// cmd + shift + z (doesn't work)
UIKeyCommand(input: "z", modifierFlags: [.command, .shift], action: #selector(redo)),
// z (works)
UIKeyCommand(input: "z", modifierFlags: [], action: #selector(z)),
]
}
// this doesn't help
override var undoManager: UndoManager? { return nil }
// undo
@objc private func undo() {
print("undo")
}
// redo
@objc private func redo() {
print("redo")
}
// z
@objc private func z() {
print("z")
}
}
You can do this with a UITextView+UIResponder.swift extension:
import UIKit
extension UITextView {
static var myUndoManager = UndoManager()
fileprivate func handleUndo () { ... }
fileprivate func handleRedo () { ... }
override var undoManager : UndoManager? {
return Self.myUndoManager
}
override func pressesBegan (
_ presses: Set<UIPress>
, with event: UIPressesEvent?
)
{
for press in presses {
guard
let key = press.key
, key.charactersIgnoringModifiers == "z"
else { continue }
switch key.modifierFlags {
case .command:
handleUndo()
case [ .command, .shift]:
handleRedo()
default:
break
}
}
super.pressesBegan (
presses
, with: event
)
}
}
Relevant Apple References:
UIResponder::func pressesBegan(_:)
https://developer.apple.com/documentation/uikit/uiresponder
Keyboards & Input::class UIKey
https://developer.apple.com/documentation/uikit/uikey
See Also: uiresponder https://stackoverflow.com/questions/tagged/uiresponder
keyCommands
work?UITextView is opaque, so I can't see for myself , but I think it overrides pressesBegan(_:with:)
and does not call super
for any key-press it handles. Without that call to super
, UIPressesEvent
events never propagate up the responder chain; keyCommands
will never see them.