覆盖 UITextView 的 CMD + Z 键命令
Posted
技术标签:
【中文标题】覆盖 UITextView 的 CMD + Z 键命令【英文标题】:Override UITextView's CMD + Z key command 【发布时间】:2021-05-19 06:22:39 【问题描述】:是否可以覆盖UITextView
对cmd + z
和cmd + shift + z
的处理?
我试过了
覆盖keyCommand
属性,但永远不会调用选择器..
覆盖undoManager
,这也无济于事
class 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")
【问题讨论】:
反馈提交:FB9111541 【参考方案1】:您可以使用 UITextView+UIResponder.swift 扩展来做到这一点:
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
)
相关的 Apple 参考资料:
UIResponder::func pressesBegan(_:)
https://developer.apple.com/documentation/uikit/uiresponder
Keyboards & Input::class UIKey
https://developer.apple.com/documentation/uikit/uikey
另见:uiresponder https://***.com/questions/tagged/uiresponder
为什么覆盖 keyCommands
不起作用?
UITextView 是不透明的,所以我自己看不到,但我认为它会覆盖 pressesBegan(_:with:)
并且不会为它处理的任何按键调用 super
。如果没有对super
的调用,UIPressesEvent
事件永远不会向上传播到响应者链; keyCommands
永远不会看到他们。
【讨论】:
不错的答案!但这将禁用关键命令的重复,有没有办法保留它? 您可以在 pressesBegan 中启动 Timer,然后在 pressesEnded 中使 Timer 无效并停止 @HassanTaleb 我不确定“重复”是什么意思;你的意图是只剥离 UITextView 的撤消/重做职责并保持它处理的所有其他内容不受影响(这不是我对 OP 问题的解释)?如果是这样,那么您需要正确子类化 UITextView,并调整我的答案,使其仅在用户意图执行除 Undo/Redo 之外的 other 操作时调用 super.pressesBegan(_:with:) .如果您发布这样的问题,我很乐意回答。 重复我的意思是按钮 (CMD + z) 保持按下状态,函数“handle Undo()”重复调用@Jason @HassanTaleb youjin 的建议似乎不错:在扩展中添加一个静态 Timer,使用handleUndo()
中的 Timer.scheduledTimer(withTimeInterval:repeats:block:) 设置它,实现 pressesChanged/Ended/Cancelled 这样他们都使静态计时器无效。以上是关于覆盖 UITextView 的 CMD + Z 键命令的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法覆盖 UITextView UIKeyInput 以便可以从超级视图输入文本?
Mac Catalyst 无法使用 pressesBegan 覆盖捕获 .command 键修饰符