ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
Appで外部キーボードをサポートする
あなたのAppで外部キーボードが使えると、より体感的で馴染みのあるタイピング体験を提供できるだけでなく、素早いナビゲーションやキーボードショートカットを利用することもできるようになります。あなたのiPadOSやMac Catalyst Appで、外部キーボードをサポートする最適な方法を学びましょう:レスポンダチェーンへの理解を深め、カスタムキーボードショートカットを実装する際のベストプラクティスをご紹介します。一般的なシステムキーボードショートカットを導入・実行し、ジェスチャ認識でモディファイアを利用、未処理のキーボードイベントAPIを活用、key downとkey upイベントに容易に対応する方法についても説明します。
リソース
関連ビデオ
WWDC22
WWDC21
WWDC20
WWDC19
-
ダウンロード
こんにちは WWDCへようこそ “アプリケーションで 外部キーボードをサポートする” iOS Keyboardsチームの ジェームズ・メガハンです ハードウェアキーボードを備えたデバイスで アプリケーションを最高のものにする方法を 簡単に説明します
iOSアプリケーションはタッチに 万能に設計したUIを常に採用してきました これはコンテンツと対話するための 本当に優れた方法です アプリケーションでUIを見つけることは 画面に何かを表示するのと 同じくらい簡単です しかし ハードウェアキーボードを 接続したiPadユーザーが かなり一般的になってきました アプリケーションに ハードウェアキーボードを埋め込むことで ユーザーはより生産的になり UIをより迅速に 人間工学的に操作できるようになります 考えることなく反射的に 機能を実行できます また 標準システムの ショートカットの実装により 初心者ユーザーが期待していて Macからもたらされる なじみのある一貫したインターフェイスで アプリケーションにアプローチできます iPadのような次世代コンピューティング プラットフォームで 最高のアプリケーションとするには タッチ操作とハードウェアキーボード操作の 両方で優れている必要があります
これが今日お話しする内容です キーボードショートカットから はじめましょう iOSでキーボードショートカットが どのように機能するか説明するために UIKeyCommandについてお話しします UIKeyCommandは カスタムキーボードショートカットを 表すオブジェクトです 期待するすべてのプロパティを備えています 例えば ユーザーに表示される discoverbilityTitle オブジェクトを呼び出すために必要な キーボード入力 また オプションで 押される修飾キーを定義する― modifierFlagsのセットなどです これはUIResponderのkeyCommandsと呼ばれる オーバーライド可能なプロパティを介して キーコマンドの配列を返すことで UIと連携して機能します その特定のレスポンダの すべてのコマンドの配列を返すようにします ほとんどの一般的なUIKitウィジェットは すでにUIResponderのサブクラスです そのため これらのキーコマンドを含めるために アプリケーションを拡張するのは この1つのプロパティを オーバーライドし UIの特定の部分に関連する キーコマンドを返すだけの簡単なものです アプリケーションで すべてを機能させる方法は レスポンダチェーンを介して行われます レスポンダチェーンはアプリケーションの ビュー階層に緩やかに従います UIApplicationインスタンスが最後にあり ユーザーが対話しているレスポンダが 最初にあります アプリケーションの最初のレスポンダは UIResponderオブジェクトで すべてのキーボードイベントが 最初に到達します チェーンでレスポンダが特定のイベントを 処理できない場合 そのイベントはチェーンのさらに上へいきます 例えば UIViewsは チェーン内の指定された次のレスポンダを ビューのスーパービューとして持っています
つぎに アプリケーションにより キーコマンドが各レスポンダから オーバーライドしたkeyCommandsを介して 収集されます アプリケーションの 最初のレスポンダから始まり 最上位の UIApplicationインスタンスで終了します システムによりすべてのキーコマンドが 収集されると ユーザーは見つけやすいHUDで それらを発見できます HUDはシステム内の任意の場所で コマンドキーを長押しすることで アクセスできます これはユーザーがキーボードショートカットを 発見できるだけでなく 開発中にすべてを1ヵ所で テストおよび検査するのに便利です それでは実際に これらを どのように組み合わせるか見てみましょう ミュージックアプリケーションを 例にあげます アプリケーションが最前面にあるとき ユーザーはスペースバーを押して 再生中の音楽を 簡単に切り替えることができます これはメディア再生を行う すべてのアプリケーションで一貫して機能します 写真アプリケーションでのビデオ再生や SafariのQuickTimeビデオなどです Model-View-Controllerパターンに従い この動作を定義するための理想的な場所は カスタムビューコントローラのサブクラスです この例では UIViewControllerの PlayerViewController サブクラスがあります これはアプリケーションで再生を管理し ビューには再生ボタンなどが含まれています すべてのUIViewControllersは UIRespondersのため ここではいくつかのメソッドを オーバーライドするだけで キーボードショートカットの 受け入れを開始できます まずcanBecomeFirstResponderを オーバーライドしてtrueを返します 次に viewDidAppearをオーバーライドし becomeFirstResponderを呼び出して このビューコントローラが最初に表示されるとき 最初のレスポンダになるようにします 最後にkeyCommandsプロパティを オーバーライドし カスタムのスペースバー キーボードショートカットを返します ここではセレクターで指定した 呼び出されたときに 実行するactionと必要なinputを HUDに表示するための ローカライズされた文字列を提供しています この場合 スペースのみを含む文字列で スペースバー用であることを示します ワクワクしてきたでしょう ユーザーが期待している よく使用されるキーボードショートカットを アプリケーションに追加することを考えると 例えば ミュージックライブラリで 作業している場合 全選択やコピー ペーストのような いくつかのショートカットを加え 音楽とプレイリストの操作を より簡単にします または イラストレーションで作業していれば Command + で拡大し Command - で縮小するような ショートカットを加えるでしょう 幸いなことに これらの一般的な キーボードショートカットの多くは 単一のUIKeyCommandを 作成する必要がありません いくつかのメソッドを オーバーライドするだけでよいのです すべてのUIResponderサブクラスは UIResponderStandardEditActionsと呼ばれる プロトコルに準拠しており それはここにリストされている 任意のメソッドに応えます 関連するメソッドをオーバーライドするだけです 単一のUIKeyCommandの作成は不要です これは簡単な例です UIResponderサブクラスには UITableViewControllerサブクラスがあります 前に行ったのと同じ2つのメソッドを オーバーライドし それが最初のレスポンダになることを確認します いつものように これを ビューコントローラサブクラスの内部に 実装する場合必要になります そして 前に述べた任意のメソッドを オーバーライドできます 全選択やコピーペーストなど いずれにも単一のUIKeyCommandの 作成は不要です UIResponderStandardEditActionsの ドキュメントで より多くのコマンドと詳細を 調べてみてください UIKeyCommandはCatalystを 念頭に設計されました これらの新しいキーコマンドは非常に簡単に macOSのメニューバーで機能させられます 前に説明した UIResponderStandardEditActionsは 無料で入手できます しかし カスタムUIKeyCommandsの場合 UIKeyCommandはUICommandのサブクラスです つまりこれは macOS Catalinaに導入した command builder APIに簡単に統合できます command builder APIについて より深く詳しい情報を知るには WWDC 2019のセッション “Taking iPad Apps for Mac to the Next Level”をご覧ください
次に お話ししたいことは ハードウェアキーボードがテーブルビューおよび コレクションビューと作用する方法です ファイルのリストがある場合 ユーザーはMacの一般的なショートカットが iPadでも機能することを期待します 例えば シフトキーを押しながら 2つのリスト項目をクリックして 連続するファイルのリストを 選択できる機能です 次に コマンドキーを押しながら リストの複数の項目をタップすると 最初に編集モードに入る必要なく ユーザーの選択を拡張できます UITableViewかUICollectionViewを 使用している場合 ユーザーが期待する この動作を 非常に簡単に実装できます shouldBeginMultipleSelectionInteractionAt indexPathを実装し trueを返すことだけです それによりシステムは自動的に テーブルビューを編集モードにするか コレクションビューを複数選択モードにし 押されている修飾キーに基づき ユーザーが現在選択している― インデックスパスのセットを拡張します 同様に didBeginMultipleSelectionInteractionAt indexPathを実装し 周囲のUIを自動的に 編集モードに対応させます 複数選択のAPIが他に提供できることは 2019年のセッション“Modernizing Your UI for iOS 13”で確認できます つぎは iOS14の新しい機能についてです ジェスチャ認識に追加したことについて お話しします Numbersで別の例を見ていきましょう NumbersがiPadの ハードウェアキーボードを活用し 高度な機能を提供する方法の1つは ユーザーがシフトキーを押しながら 指かトラックパッドで 図形のサイズを変更しながら 選択した図形のスケールを アスペクト比に制限できるようにすることです さらに Numbersでは ユーザーはコマンドキーを押したまま 複数のオブジェクトをタップして 選択できるため オブジェクトを一度に動かすことができます このすべては iOS 13.4で 新しいMagic Keyboardを導入した際― UIGestureRecognizerにmodifierFlagsという プロパティを追加したことで可能になりました これによりどのアプリケーションでも このような動作を実装できます このプロパティは ジェスチャ認識のステータスが変化する際― ユーザーが押している修飾キーに設定されます この例でNumbersが行ったようなことを 実装する場合に必要なのは ジェスチャ認識のコールバックが発生したときに このプロパティを調べ 押された修飾キーに基づき 適切なアクションを実行することです イベントとジェスチャ認識の 新機能の詳細については “Handle Trackpad and Mouse Input” セッションをご覧ください 最後にAPIについてお話しします Rawキーボードイベントに応答するものです アプリケーション内でハードウェアと キーボードの操作を利用すると ユーザーはアプリケーションを特定の場面で より正確に制御できます Numbersの例に戻りましょう Numbersはハードウェアキーボードの 精度を活用し ユーザーが矢印キーを使用して 図形やレイヤーを微調整したいという 期待に応えます これには key downイベントで オブジェクトを動かし始め key upイベントで オブジェクトを停止する必要があります どちらもUIKeyCommandsでは 実行できず ユーザーに呼び出されたときにのみ 発生します iOSの新機能として 接続されたハードウェアキーボードからの すべてのkey downおよびkey upイベントに 応答する機能を追加しました レスポンダチェーンに戻ります すべてはpressesBeganおよびpressesEndedという UIResponderメソッドを介し実行されます 2つのメソッドを ビューかビューコントローラで オーバーライドするだけで キーが押されたときや離されたときに 通知を受け取ります 繰り返しますが Model-View-Controllerパターンを使用し キャンバスビューコントローラのようなもので pressesBeganとpressesEndedを オーバーライドします pressesBeganは ハードウェアキーボードで キーが押されると呼び出され キーコードをチェックして 押された矢印キーを確認し アプリケーションで適切なアクションを実行し キーが押されている間 図形の移動を続けることができます それからpressesEndedで アプリケーションでアクションを実行するだけで 図形の移動が停止します 同じくらい簡単です 同様に ジェスチャ認識に追加したものと同じく すべてのキーイベントのmodifierFlagsを確認し 必要に応じた調整も可能です 例えば ユーザーが シフトキーを押したまま 何かを移動しながら選択できるようにします さらに 修飾キーだけで key downとkey upイベントについて通知します 最後に 次にすべきことをお話しします あなたのアプリケーションで― 一般的なキーボードショートカットが 機能することを確認してください 完全にカスタマイズされた キーボードショートカットを使用することで アプリケーションの機能を強化し ユーザーの生産性を高めましょう アプリケーションがmacOSに馴染むように メニュー項目を作成してください 最後に 新しい Hardware Keyboard APIを使って 素晴らしいキーボード体験を 完成してください ありがとうございました チャンネル登録をお願いします
一瞬 頭が真っ白に
-
-
0:01 - PlayerViewController
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: " ") ] } }
-
0:02 - SongListTableViewController
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?) { … } }
-
0:03 - UIKeyCommand
class UIKeyCommand : UICommand { ... } override func buildMenu(with builder: UIMenuBuilder) { builder.replaceChildren(ofMenu: .file) { children in return [ UIKeyCommand() ] + children } }
-
0:04 - Extending selection with keyboard
optional func tableView(_ tableView: UITableView, shouldBeginMultipleSelectionInteractionAt indexPath: IndexPath) -> Bool optional func tableView(_ tableView: UITableView, didBeginMultipleSelectionInteractionAt indexPath: IndexPath)
-
0:05 - recognizedDragGesture
func recognizedDragGesture(_ panGesture: UIPanGestureRecognizer) { if panGesture.modifierFlags.contains(.command) { snapToGrid = true } else if panGesture.modifierFlags.contains(.shift) { constrainAspectRatio = true } ... }
-
0:06 - Responding to raw keyboard events
class UIResponder: NSObject { func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent) func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent) }
-
0:07 - CanvasViewController
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() } }
-
0:08 - CanvasViewController modifier flags
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() } } } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。