🤖

NSTextFieldでNSEventのキーを見てアクションを実行するサンプルコード

2023/03/12に公開

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
    }
            
}

おわりです。

GitHubで編集を提案

Discussion