WWDC Quick Look 💓 By SwiftGGTeam
Support hardware keyboards in your app

Support hardware keyboards in your app

元の動画を見る

ハイライト

UIKit のハードウェア キーボード サポートはレスポンダー チェーン上に構築されています。アプリは UIKeyCommand と UIResponderStandardEditActions を使用して検出可能なショートカット キーを提供し、UITableView/UICollectionView の複数選択コールバックを使用して Shift/Command 選択に応答し、UIGestureRecognizer.modifierFlags と pressesBegan/pressesEnded を使用して修飾キー ジェスチャとキーを処理できます。プレス/リリースイベント。

主要内容

iPad アプリはもともとタッチを中心に設計されました。画面上にボタンが表示され、クリックするだけで機能を見つけることができます。外付けハードウェア キーボードが日常的に使用されるようになると、別の期待が生まれました。ユーザーは、Space を使用して再生を制御し、Command を使用してショートカット キーを見つけ、Shift または Command を使用してリストの選択を拡張し、矢印キーを使用してキャンバス オブジェクトを微調整したいと考えていました。

このセッションでは、まずイベントの由来について説明します。キーボード イベントがレスポンダー チェーンに入ります。現在、ファーストレスポンダが最初にイベントを受信します。処理できない場合、イベントはチェーンを上流に進みます。 UIKit は、このチェーンに沿って各レスポンダーの公開データを収集します。keyCommandsをクリックし、Command キーを押し続けると表示される検出可能 HUD にそれらを表示します。

その後、スピーチによりキーボードのサポートが 4 つの層に分割されました。最初のレベルはカスタム ショートカット キーです。使用します。UIKeyCommand入力とセレクターを接続します。 2 番目のレベルは標準の編集アクションです。selectAll(_:)copy(_:)paste(_:)これらの方法では、追加のショートカット キーを作成する必要はありません。 3 番目のレベルはリスト ビューとコレクション ビューでの複数選択で、システムは Shift または Command に基づいて選択を展開します。 4 番目の層は下位レベルの入力です。ジェスチャ認識機能は修飾キーを読み取ることができます。UIResponderキーダウン、キーアップにダイレクトに反応します。

このモデル セットは Mac Catalyst にも対応しています。UIKeyCommand継承元UICommand、コマンド ビルダー API を入力して、macOS メニュー バーに表示できます。開発者は、iPad と Mac 用に 2 つの完全に別個のコマンド ポータルを維持する必要がなくなりました。

詳細

1. UIKeyCommand を使用してカスタム ショートカット キーを公開する

01:17UIKeyCommandアプリ独自に定義されたキーボード ショートカットを表します。これには、発見可能性のタイトル、トリガー入力、オプションの修飾子フラグ、および呼び出されたときに実行するアクションが含まれます。 UIKitパスUIResponder.keyCommandsレスポンダー チェーンからこれらのコマンドを収集します。

(03:14) このスピーチでは、例として音楽の再生コントロールを使用しています。プレーヤー ビュー コントローラーがファーストレスポンダーになった後、スペース キーでトリガーできるようになります。playPause

class PlayerViewController: UIViewController {

    override var canBecomeFirstResponder: Bool {
        return true
    }

    override func viewDidAppear(_ animated: Bool) {
        becomeFirstResponder()
    }

    override var keyCommands: [UIKeyCommand]? {
        return [
            UIKeyCommand(title: NSLocalizedString("PLAY_PAUSE", comment: "…"),
                        action: #selector(playPause),
                         input: " ")
        ]
    }
}

キーポイント:

  • canBecomeFirstResponder戻るtrue、このビュー コントローラーはキーボード イベント エントリになることができます。 -viewDidAppear(_:)電話becomeFirstResponder()、プレーヤー インターフェイスは、ショートカット キーが表示された直後に受け取ることができます。 -keyCommands現在のインターフェースで使用可能なコマンドの配列を返します。 -input: " "スペースバーをバインドしますplayPause セレクター。
  • titleCommand キーを長押ししたときにシステムがユーザーに表示するローカライズされた文字列を使用します。

2. 標準の編集アクションでは、UIKeyCommand を手書きする必要はありません。

(04:31) 多くのショートカット キーには、すでにシステム規則があります。音楽ライブラリやファイルリストでよく使われる「全選択」「コピー」「ペースト」は以下に属します。UIResponderStandardEditActions。レスポンダー サブクラスの対応するメソッドをオーバーライドする限り、UIKit は共通の編集ショートカット キーをこれらのアクションに接続できます。

class SongListTableViewController: UITableViewController {

    override var canBecomeFirstResponder: Bool {
        return true
    }

    override func viewDidAppear(_ animated: Bool) {
        becomeFirstResponder()
    }

    /* UIResponderStandardEditActions */

    override func selectAll(_ sender: Any?) {  }

    override func copy(_ sender: Any?) {  }

    override func paste(_ sender: Any?) {  }

}

キーポイント:

  • UITableViewControllerあまりにもUIResponder、レスポンダー チェーンに直接参加できます。 -selectAll(_:)copy(_:)paste(_:)からUIResponderStandardEditActions
  • これらの標準アクションを使用する場合、作成する必要はありませんUIKeyCommand
  • この書き方により、ユーザーは期待どおりに Mac から Command-A、Command-C、および Command-V を iPad アプリに持ち込むことができます。

(05:52) カスタム コマンドが Mac Catalyst メニュー バーに入ると、次のことができます。UIKeyCommandとしてUICommandコマンドビルダーを入れます。

class UIKeyCommand : UICommand {
    ...
}

override func buildMenu(with builder: UIMenuBuilder) {
    builder.replaceChildren(ofMenu: .file) { children in
        return [ UIKeyCommand() ] + children
    }
}

キーポイント:

  • UIKeyCommandはいUICommandサブカテゴリ。 -buildMenu(with:)これは、コマンドのメニュー構造へのエントリ ポイントです。 -replaceChildren(ofMenu:)指定したメニューのサブ項目を置換または補足できます。
  • Mac Catalyst アプリの場合、キーボード ショートカットとメニュー項目は同じコマンド モデルのセットを指す必要があります。

3. テーブル ビューとコレクション ビューでキーボードによる複数選択をサポートする

(06:28) アプリにファイルリストがある場合、ユーザーは Shift クリックで連続した項目を選択し、Command クリックで連続していない選択を展開することを期待します。UITableViewそしてUICollectionView対応する複数選択コールバックが提供されています。

optional func tableView(_ tableView: UITableView,
       shouldBeginMultipleSelectionInteractionAt indexPath: IndexPath) -> Bool

optional func tableView(_ tableView: UITableView,
       didBeginMultipleSelectionInteractionAt indexPath: IndexPath)

キーポイント:

  • shouldBeginMultipleSelectionInteractionAt戻るtrueその後、システムは複数選択インタラクションの処理を開始します。
  • テーブル ビューは編集モードになり、コレクション ビューは複数選択モードになります。
  • システムは、ユーザーが Shift キーを押すか Command キーを押すかに基づいて現在の選択を展開します。 -didBeginMultipleSelectionInteractionAt一括操作バーの表示など、周囲のUIを更新するのに適しています。

4. ジェスチャ認識機能でキーボード修飾キーを読み取る

(07:47) iOS 13.4 が追加されましたUIGestureRecognizer.modifierFlags。これは、Gesture Recognizer の状態が変化したときにユーザーがどのキーボード修飾キーを押したかを記録します。数値の例としては、Shift キーを押しながら図形のサイズを変更するときに縦横比を維持することや、Command キーを押しながら複数のオブジェクトを選択することが挙げられます。

func recognizedDragGesture(_ panGesture: UIPanGestureRecognizer) {

    if panGesture.modifierFlags.contains(.command) {
        snapToGrid = true
    } else if panGesture.modifierFlags.contains(.shift) {
        constrainAspectRatio = true
    }

    ...
}

キーポイント:

  • modifierFlags現在のジェスチャ認識機能では、キーボードを個別に聞く必要はありません。 -.commandグリッド スナップなどの正確な編集モードに切り替えることができます。 -.shiftアスペクト比を維持する制約モードに切り替えることができます。
  • このタイプの対話は、描画、植字、表、地図編集などの専門的なシナリオに適しています。

5. pressesBegan と pressesEnded を使用して元のキー イベントに応答する

09:00UIKeyCommandショートカット キーがトリガーされたときに 1 回だけ呼び出されます。矢印キーを使用してキャンバス オブジェクトを移動するなどの操作では、キー ダウンとキー アップを区別する必要があります。押すと移動が開始され、放すと移動が停止します。新しい生のキーボード イベント エントリは次のとおりです。UIResponder.pressesBegan(_:with:)そしてUIResponder.pressesEnded(_:with:)

class UIResponder: NSObject {
    func pressesBegan(_ presses: Set<UIPress>,
                     with event: UIPressesEvent)

    func pressesEnded(_ presses: Set<UIPress>,
                     with event: UIPressesEvent)
}

キーポイント:

  • pressesBeganハードウェア キーボードのキーが押されたときに呼び出されます。 -pressesEndedキーが放されたときに呼び出されます。
  • これら 2 つの方法は、継続的なアクションに適していますが、1 回だけトリガーされるメニュー コマンドには適していません。
  • 元のキー イベントは引き続きレスポンダー チェーンを通過するため、ビューまたはビュー コントローラーに配置できます。

(09:59) キャンバスの例:pressesBegan矢印キーをチェックインしますpressesEnded動くのをやめてください。

class CanvasViewController: UIViewController {

     override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
         for press in presses {
             guard let key = press.key else { continue }
             switch key.keyCode {
             case .keyboardUpArrow: startMoveUp()
             case .keyboardDownArrow: startMoveDown()

             }
     }
     }

     override func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
         stopMoving()
     }

}

キーポイント:

  • press.key空の可能性があるため、最初に使用してくださいguardキーなしで押すとスキップします。 -key.keyCode上下などの特定のボタンを区別できます。 -startMoveUp()そしてstartMoveDown()方向キーを押した後の継続的な動作を表します。 -stopMoving()つけるpressesEnded、ユーザーがボタンを放した後にアクションが確実に停止するようにします。

(10:29) Raw キー イベントは修飾キーを読み取ることもできます。次の例では、オブジェクトの移動時に Shift をチェックし、「移動中に選択」動作に切り替えます。

class CanvasViewController: UIViewController {

    override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
        var selectWhileMoving = false
        for press in presses {
            guard let key = press.key else { continue }
            if key.modifierFlags.contains(.shift) {
                selectWhileMoving = true
            }

            switch key.keyCode {
            case .keyboardUpArrow: startMoveUp()

            }
        }
    }
}

キーポイント:

  • key.modifierFlags.contains(.shift)現在のキーイベントの修飾キーのステータスを直接読み取ります。 -selectWhileMovingこれはビジネス状態であり、移動と同時に選択が拡張されることを示します。
  • これはジェスチャ認識機能と同じですmodifierFlagsこれは同じインタラクティブなアイデアです。ハードウェア キーボードはモードの切り替えを担当し、タッチ、ポインター、または矢印キーはアクションの実行を担当します。

重要ポイント

  • 内容: メディア プレーヤーにスペースバーの再生/一時停止を追加します。 実行する価値がある理由: Session は明示的に Music を使用して、メディア再生アプリでスペース バーが一般的に期待されていることを示します。 開始方法: 再生インターフェイスのビュー コントローラーをファーストレスポンダーにします。keyCommands1 つを返しますUIKeyCommand、バンドルinput: " "再生状態切り替えメソッドに接続します。

  • 内容: ファイル、曲、プロジェクト リストで Command-A、Command-C、Command-V をサポートするようにします。 実行する価値がある理由:UIResponderStandardEditActionsユーザーに馴染みのある標準の編集ショートカット キーにアクセスして、カスタム コマンドの数を減らすことができます。 開始方法: リスト コントローラーでオーバーライドしますselectAll(_:)copy(_:)paste(_:)、コントローラーがファーストレスポンダーになれることを確認します。

  • 内容: Shift/Command による複数選択をリストに追加します。 これを実行する価値がある理由: デスクトップ ユーザーは、Shift キーで連続する項目を選択し、Command キーで非連続な選択を展開することを当然期待します。 UIKit は、テーブル ビューとコレクション ビューへの複数選択の入り口をすでに提供しています。 開始方法: 実装shouldBeginMultipleSelectionInteractionAtそして戻るtrue、 またdidBeginMultipleSelectionInteractionAtバッチ操作 UI は に表示されます。

  • 内容: 描画ツールまたは植字ツールに修飾キー モードを追加します。 実行する価値がある理由: スピーチ内の Numbers の例は、Shift と Command を使用すると、同じドラッグ ジェスチャでより正確な編集動作を生成できることを示しています。 開始方法:UIPanGestureRecognizerコールバックから読み取るmodifierFlags、によると.shift.commandアスペクト比の維持、グリッドへのスナップ、または複数選択モードを切り替えます。

  • 内容: 矢印キーを使用して、キャンバス オブジェクトを連続的に移動します。 実行する価値がある理由:UIKeyCommandこれは 1 回だけトリガーされ、連続的な動作にはキー ダウンとキー アップの 2 つのフェーズが必要です。 開始方法: キャンバス ビュー コントローラーでオーバーライドするpressesBeganそしてpressesEnded、によるとkey.keyCode移動を開始し、キーを放すと停止します。

関連セッション

  • トラックパッドとマウス入力の処理 — iPad および Mac Catalyst でトラックパッド、マウス、スクロール、修飾キー、および間接入力イベントを処理します。
  • iPadOS ポインター用に構築 - iPadOS ポインターの操作を設計して実装し、外部キーボード、マウス、トラックパッドのユーザーにより自然な制御フィードバックを提供します。
  • iPad 向けに設計 — レイアウト、ナビゲーション、ドラッグ アンド ドロップ、キーボード、トラックパッドの観点から、より完全な iPad アプリを設計します。
  • UICollectionView の進歩 — コレクション ビューのリスト、アウトライン、最新のセル構成を学び、キーボードの複数選択リストのより良い基盤を提供します。
  • Mac Catalyst の新機能 — Mac Catalyst のライフサイクル、拡張機能、macOS スキン、および Mac 用に最適化モードについて学びます。

コメント

GitHub Issues · utterances