🤖
NSTextFieldでNSEventのキーを見てアクションを実行するサンプルコード
swiftを使ったサンプルです。NSControlTextEditingDelegate.control(_:textView:doCommandBy:)を使います。
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
switch commandSelector {
case #selector(insertNewline):
// このdelegateメソッドの基本的な使い方はこちら.
doSomethingYouWant()
// 自前ハンドリング**する場合はtrueを返す**
return true
default:
/*
Field Editorで定義されているイベント以外に実行したいキーイベントはNSEventを見て実行させる
*/
guard let currentEvent = view.window?.currentEvent, currentEvent.type == .keyDown else {
return false
}
let modifierFlags = currentEvent.modifierFlags.intersection(.deviceIndependentFlagsMask)
let firstKeyInputScalar = currentEvent.charactersIgnoringModifiers?.unicodeScalars.first
// ネットではkeyCode == 36というハードコードをよく見るが、ハードコードあんまよくないなぁと思ってNSEvent.SpecialKeyのunicodeスカラと比較するようにしている
let isTargetKeyPressed = firstKeyInputScalar == NSEvent.SpecialKey.enter.unicodeScalar || firstKeyInputScalar == NSEvent.SpecialKey.carriageReturn.unicodeScalar
// このケースではcontrol + (enter or return)が押された場合に自前処理を実行している
if modifierFlags == [.control] && isTargetKeyPressed {
doSomethingYouWant()
return true
}
}
return false
}
Shift + EnterとEnterを判別する
通常、NSTextFieldではShift + EnterとEnterは両方ともinsertNewline
のメソッドを実行するのですが、
Numbersのように「Shift + Enterでは上のセルにフォーカスを移動し、Enterで下のセルにフォーカスする」という挙動を実現したい場合は、少しコードを変える必要があります。
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
guard let currentEvent = view.window?.currentEvent, currentEvent.type == .keyDown else {
return false
}
let modifierFlags = currentEvent.modifierFlags.intersection(.deviceIndependentFlagsMask)
switch commandSelector {
case #selector(insertNewline):
if modifierFlags == .shift {
// Shift + Enterの際のコマンド
} else {
// Enterの時のコマンド
}
return true
default:
return false
}
}
おわりです。
Discussion