ハイライト
tvOS 14 用
UISearchController検索候補を追加すると、アプリケーションで使用できますUISearchSuggestionItemまたはカスタマイズするUISearchSuggestionユーザーが入力すると、アイコンとアクセシビリティの説明を含む候補が表示され、提案が選択された後にコンテンツ タイプごとに結果が更新されます。
主要内容
Apple TV ではモバイルよりも検索コストが高くなります。ユーザーはリモコンを持ち、オンスクリーン キーボード上で単語ごとにフォーカスを移動します。検索ボックスのテキストが小さすぎ、キーボードの占有スペースが大きすぎ、結果領域が圧縮されるため、ビデオや写真を見つけるのが遅くなります。
tvOS 14 では、まずシステム検索インターフェイスが変更されました。検索ボックスのテキストが大きくなり、多言語キーボードが単一行レイアウトに最適化され、結果領域のスペースが増えました。アプリケーションが使用している限りUISearchController、これらのインターフェイスの改善はシステムに付属します。
このセッションの焦点は、新しい検索の提案です。ユーザー入力blueを使用すると、アプリケーションはユーザーが完全なキーワードを入力するのを待つ必要がありません。 「青いビデオ」や「青い写真」などの候補をすぐに提示してくれます。提案自体にもアイコンとアクセシビリティの説明を含めることができるため、ユーザーが提案を選択すると、アプリはそれがビデオの提案であることを認識し、ビデオの結果のみを表示します。
デモ プロジェクトは、写真とビデオのハイブリッド旅行アプリです。まず検索ページをタブバーに配置してから、UISearchControllerコレクションビューの結果を駆動し、最終的にアクセスしますUISearchSuggestionを使用すると、入力が入力されるとリアルタイムで候補リストを更新できます。
詳細
検索ページを tvOS タブ バーに接続します
(01:40) デモからSearchViewController始める。このコントローラーは、後続のすべての検索結果と候補が抽出されるデータ ソースを保持します。appDataクエリ。
private let appData: AppData
init(appData: AppData) {
self.appData = appData
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
キーポイント:
private let appDataコントローラー内の検索データ ソースを修正します。init(appData:)検索ページを作成するときに、呼び出し元に同じデータ ソースを渡します。super.init(nibName:bundle:)純粋なコードを使用してコントローラーを作成します。init?(coder:)実装がないことは、この例がストーリーボードのデコード パスに従っていないことを示しています。
(01:51) 検索エントリでは、システム標準のタブ バー項目を使用する必要があります。このようにして、ユーザーは Apple TV 上でその目的を直接確認できます。
// use the system standard search tab bar item
tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarItem.SystemItem.search, tag: 0)
キーポイント:
UITabBarItem.SystemItem.searchシステムを使用してアイコンを検索し、コピーします。tag: 0これはタブ バー項目の識別子であり、この例では追加のロジックはありません。- このコードは入力の問題を解決していますが、検索入力ボックスはまだ作成されていません。
### 使用UISearchContainerViewControllerホスト検索コントローラー
(02:05) 検索コントローラーはサブコントローラーとしてページに追加されるため、セッション使用UISearchContainerViewController包みます。
private let searchController: UISearchController
private let searchContainerViewController: UISearchContainerViewController
キーポイント:
searchController検索バーを管理し、変更や提案を入力します。searchContainerViewController検索コントローラーを現在のページに埋め込む役割を果たします。- 両方のプロパティが配置されます
SearchViewController内部では、ライフサイクルは検索ページと一致しています。
(02:11) 検索結果は既存のsearchResultsControllerそれを見せて、伝えてくださいUISearchController。
self.searchController = UISearchController(searchResultsController: self.searchResultsController)
self.searchContainerViewController = UISearchContainerViewController(searchController: searchController)
キーポイント:
UISearchController(searchResultsController:)結果ページをシステム検索コントローラーに渡して管理します。UISearchContainerViewController(searchController:)検索 UI を子コントローラーとして埋め込み可能にします。- 将来的には、結果コントローラーを更新するだけです
itemsをクリックすると、コレクション ビューを更新できます。
(02:16) 子コントローラーは、親コントローラーに参加するには、UIKit の封じ込めプロセスに従う必要があります。
override func viewDidLoad() {
addChild(searchContainerViewController)
searchContainerViewController.view.frame = view.bounds
view.addSubview(searchContainerViewController.view)
searchContainerViewController.didMove(toParent: self)
}
キーポイント:
addChildまず、コントローラーの親子関係を確立します。searchContainerViewController.view.frame = view.bounds検索コンテナが現在のページを埋めるようにします。view.addSubview検索コンテナ ビューを階層に追加します。didMove(toParent:)UIKit 子コントローラーの追加プロセスを完了します。
(03:17) 検索結果はコレクションビューとなっており、結果に合わせて検索バーをスクロールする必要があります。
// scroll search controller allong with results collection view
searchController.searchControllerObservedScrollView = searchResultsController.collectionView
キーポイント:
searchControllerObservedScrollView結果リストへのポインタcollectionView。- ユーザーが結果をスクロールすると、検索コントローラーはシステムの予期される tvOS 動作に従って移動します。
- このステップでは、スクロール関係のみを処理し、検索フィルタリングは処理しません。
入力したテキストで検索結果を更新します
(03:43) 検索コントローラーが渡されましたsearchResultsUpdater手は現在のコントローラーに変更を入力します。
searchController.searchResultsUpdater = self
キーポイント:
selfに従う必要があるUISearchResultsUpdating。- ユーザー入力が変更されるたびに、システムは update メソッドを呼び出します。
- このエントリは、後で提案された選択されたシーンを処理するためにも使用されます。
(04:00) 最も基本的な検索ロジックは、検索バーのテキストを読み取り、データ ソースを使用して写真とビデオをフィルタリングすることです。
func updateSearchResults(for searchController: UISearchController) {
if let searchText = searchController.searchBar.text {
// get search results for 'searchText' from data source
let (results, _) = appData.searchResults(seachTerm: searchText, includePhotos: true, includeVideos: true)
searchResultsController.items = results
} else {
// no search text, show unfiltered results
searchResultsController.items = appData.allEntries
}
}
キーポイント:
searchController.searchBar.text現在の入力内容を取得します。appData.searchResults写真とビデオを同時に検索します。searchResultsController.items = resultsインターフェースリフレッシュ用のキー割り当てです。 ・入力がない場合は例に戻ります。appData.allEntries、フィルタされていないコンテンツが表示されます。
静的な検索候補を追加する
(05:30) tvOS 14 新しいUISearchSuggestionItem。これはシステムによって提供される推奨モデルであり、テキスト、説明、アイコンを配置できます。
let suggestion1 = UISearchSuggestionItem(localizedSuggestion: "Result1", localizedDescription: "Result1", iconImage: nil)
let suggestion2 = UISearchSuggestionItem(localizedSuggestion: "Result2", localizedDescription: "Result2", iconImage: nil)
searchController.searchSuggestions = [suggestion1, suggestion 2]
キーポイント:
localizedSuggestionユーザーに表示される推奨テキストです。localizedDescription提案を説明するために使用され、セッションはアクセシビリティを提供することを明示的に述べています。iconImage候補にアイコンを追加できます。まずここにアップロードしてくださいnil。searchController.searchSuggestions一連の提案を受け取り、システムがそれらを表示します。
ビジネスオブジェクトを準拠させるUISearchSuggestion
(07:05) アプリにすでに独自のデータ モデルがある場合は、そのモデルを準拠させることができますUISearchSuggestion。デモ中SuggestedEntry名前とコンテンツ タイプを検索 UI に直接公開します。
var localizedSuggestion: String? {
return self.name
}
var iconImage: UIImage? {
return self.isVideo ? UIImage(systemName: "video") : UIImage(systemName: "photo")
}
キーポイント:
localizedSuggestionモデル自身を返すname、提案オブジェクトの別のレイヤーの作成を避けるため。iconImageによるとisVideo選ぶvideoまたはphotoシンボル。- これらのシンボル画像は、限られたスペース内でコンテンツの種類を区別するために使用されます。
(07:20) 提案にはアクセシビリティの説明も提供する必要があります。この例では、名前とコンテンツ タイプを一緒にローカライズします。
var localizedDescription: String? {
if (self.isVideo) {
return String.localizedStringWithFormat(NSLocalizedString("%@ - Video", comment: ""), self.name)
}
return String.localizedStringWithFormat(NSLocalizedString("%@ - Photo", comment: ""), self.name)
}
キーポイント:
localizedDescriptionタイトルを繰り返すだけでなく、二次的な説明を返します。self.isVideo説明内のコンテンツのタイプを決定します。NSLocalizedStringそしてString.localizedStringWithFormat説明をローカライズに合わせて調整します。- これは、セッションの冒頭で述べた国際キーボードと言語サポートを反映しています。
提案を選択した後、コンテンツ タイプでフィルタリングします
(09:01) tvOS 14 の拡張UISearchResultsUpdating。ユーザーが検索候補を選択すると、システムはUISearchSuggestion新しい更新メソッドを渡します。
func updateSearchResults(for searchController: UISearchController, selecting searchSuggestion: UISearchSuggestion) {
if let searchText = searchController.searchBar.text {
var includePhotos = true;
var includeVideos = true;
}
}
キーポイント:
- メソッドのシグネチャが多すぎます
selecting searchSuggestionパラメータ。 searchText引き続き検索バーからのもので、ユーザーの現在の入力を表します。includePhotosそしてincludeVideosまずそれらを次のように設定しますtrue、デフォルトで 2 種類のコンテンツが検索されることを示します。- 候補の解析と結果の更新ロジックのために空白スペースが残されます。
(09:13) 受信した提案を自分のものに戻す例を示します。SuggestedEntry、ビデオを表すかどうかを読み取ります。
// check if the suggestion is for a photo or video
if let suggestedEntry = searchSuggestion as? SuggestedEntry {
includeVideos = suggestedEntry.isVideo
includePhotos = !includeVideos
}
キーポイント:
as? SuggestedEntryアプリ自体によって作成された提案オブジェクトのみを処理します。includeVideos = suggestedEntry.isVideo動画の候補に動画のみを表示させます。includePhotos = !includeVideos写真の提案には写真のみが表示されるようにします。- これは、提案テキストのみに依存するのではなく、提案オブジェクトによって伝えられるビジネス情報を活用します。
(09:21) 最後に、更新されたタイプ スイッチを使用してデータ ソースを再クエリします。
// filter the results by to include photos, videos, or both
let (results, _) = appData.searchResults(seachTerm: searchText, includePhotos: includePhotos, includeVideos: includeVideos)
searchResultsController.items = results
キーポイント:
searchTextユーザーが入力したキーワードを保持します。includePhotosそしてincludeVideos結果のカテゴリを決定します。appData.searchResultsフィルタリングされた結果セットを返します。searchResultsController.items = resultsコレクション ビューをすぐに更新します。
さまざまな入力方法用にスペースを確保する
(09:38) セッション 最後に、tvOS キーボードは言語と入力デバイスによって変わることを思い出させてください。 IR リモコンにはグリッド キーボードが表示されます。タイ語環境では 3 行キーボードが使用されます。結果として得られるレイアウトでは、キーボードが常に 1 行のみであることを想定することはできません。
キーポイント:
- 以前に03:17に設定されました
searchController.searchControllerObservedScrollViewスクロールリンケージを担当します。ここで重要なのは、結果領域もさまざまなキーボード レイアウトに適応する必要があるということです。 - 安全領域の外側の端の領域であっても、キーボードをカスタム UI で覆わないようにしてください。
- 提案でコンテンツ タイプを区別する必要がある場合は、セッションでシンボル イメージを使用することをお勧めします。
SF Symbols検索候補など、スペースが限られたインターフェイスに適しています。
重要ポイント
-
対処方法: 「青いビデオ」や「青いクリップ」などのビデオ アプリに「キーワード + タイプ」の検索候補を追加します。 実行する価値がある理由:
UISearchSuggestionコンテンツ タイプを保持できるため、ユーザーは提案をクリックした後にフィルタリング パネルに入る必要がありません。 開始方法: コンテンツ モデルを準拠させるUISearchSuggestion、使用isVideo生成するiconImage、存在するupdateSearchResults(for:selecting:)の設定includeVideos。 -
やるべきこと: 写真閲覧アプリに対して「場所とメディア タイプ」の提案を行います。 実行する価値がある理由: リモコンで長い地名を入力するのは非常に時間がかかります。キーボード操作を減らすことをお勧めします。 開始方法: 通常の場合
updateSearchResults(for:)中央のボタンを押してクエリ候補の場所を入力し、結果をsearchController.searchSuggestions。 -
内容: 子供向けコンテンツ アプリの提案に、明確なアイコンと音声で読み取れる説明を追加します。 実行する価値がある理由: セッションが明確に示しています
iconImageそしてlocalizedDescription、大画面インターフェイスやアクセシビリティ シナリオにおける提案の意味を説明できます。 開始方法: を使用しますUIImage(systemName:)次を使用して、コンテンツ タイプのシンボルを返します。NSLocalizedString「名前タイプ」の説明を生成します。 -
対処法: 国際化された tvOS アプリのさまざまなキーボードの高さで検索結果のレイアウトを確認します。 価値がある理由: tvOS では、言語とリモコンの種類に応じて 1 行、グリッド、または 3 行のキーボードが表示され、高さが固定された結果領域は圧縮される傾向があります。 開始方法: 結果をコレクション ビューに入れて、
searchControllerObservedScrollViewそれをポイントし、カスタム オーバーレイがキーボードを覆わないようにします。
関連セッション
- tvOS 用の SwiftUI アプリを構築する — Apple TV のフォーカス、ボタン スタイル、大画面レイアウトについて学び続けます。
- tvOS のマスター ピクチャー イン ピクチャー — 検索ページに隣接する tvOS ビデオ再生エクスペリエンスのコア機能を学びます。
- UICollectionView の進歩 - 検索結果は通常、コレクション ビューに表示され、このセッションは最新のリストおよびレイアウト機能を補完します。
- SF シンボル 2 - 検索候補内
iconImageコンテンツタイプを表現するにはSFシンボルを使用するのが適しています。 - アプリでハードウェア キーボードをサポートする - tvOS アプリがキーボード入力ユーザーを対象としている場合、このセッションは入力とナビゲーションの詳細を補足できます。
コメント
GitHub Issues · utterances