開発者向けのiOS9スポットライト検索の謎を解き明かす

公開: 2022-03-11

iOSには、Siri、Spotlight Search、Safari検索の3つの検索ポイントが組み込まれています。 iOSの最も象徴的な機能の1つであるSiriは、ほとんどのiPhoneユーザーがすでに知っているものです。 しかし、多くの人はSpotlight検索に気づいていません-Siriが存在するずっと前からiOSの不可欠な部分でした。 Spotlight Searchにアクセスするには、ホーム画面を下にスライドするか、iOS 9の新機能として、個人のホーム画面から右にスワイプします。 これにより、画面の上部に検索バーが表示されます。

iOS 8以前のこの検索ツールの焦点は電話自体の検索でした。そのため、その結果ページには、電話にあるアプリのほか、Appleアプリ内の電子メール、メッセージ、その他のプライベートアイテムが一覧表示されます。 関連性があると思われる場合は、ウィキペディアの定義も表示されます。 最後に、追加の手順としてSafari経由でWebを検索するオプションを提供します。

Spotlight Searchとは対照的に、Safariは携帯電話以外の世界のすべてです。 iOS 8では、ユーザーはSafari検索に使用する検索エンジン(Google、Yahoo、Bing、およびDuckDuckGo)を選択できます。 当然、GoogleはSafariの検索リクエストの大部分を処理します。 選択した検索エンジンに関係なく、事前に入力された検索用語がSafariに表示され、Wikipediaと一致する可能性があります。

iOS 9では、Spotlight Searchが以前よりもはるかに目立ち、スコープが広くなっています。 実際、最初に表示されるのは、使用パターンに基づいた「Siriの提案」です。 たとえば、午後にSafariを定期的に使用している場合、Siriはその頃にSafariを提案します。

そして、それはまだ「あなたの電話にあるもの」を見つける場所ですが、それは「あなたの電話にないもの」のための直接のポータルになりつつあります。 すでに近くにあるものや、Apple独自の検索エンジンを介してWebから発信されたニュースの見出しが表示され、その他のWebベースの結果が表示され始めたばかりです。

はい、AppleはiOS9用のWeb検索エンジンを作成しました。これは非常に大きな一歩です。 Applebotに挨拶します。

Spotlightと同様に、Appleが表明したSafariの目的は、Google(または他の選択されたプロバイダー)でWebを検索する機能を提供する前に、Appleの検索インデックスからの結果と提案を表示することでもあります。 iOS 9.1の時点で、Safariは、ユーザーが選択した検索プロバイダーからの結果を提供し続けることで、Spotlight検索に遅れをとっているようです。おそらく、Appleに検索機能の展開を遅くし、アルゴリズムを微調整するための時間を増やすためです。

iOS 9の発売で特にエキサイティングなのは、iOS開発者がこれらの検索機能に接続して、アプリ内からコンテンツを含めることができるようになったことです。 さらに、検索には最終的にユーザーの電話以外の結果が含まれることが約束されています。 これは大きな一歩です。

これをコンテキストに入れてみましょう。 グーグルの検索エンジンは、「SEO」を中心に構築された業界全体を生み出しました。これは、グーグルの検索を中心に資産を最適化するプロセスです。 完全に立ち上げられると、Appleの検索エンジンはモバイル検索市場の約50%を所有します。これは、検索トラフィック全体の50%(そして成長中)です。 したがって、Applebotは大きいので、「AppleMobileSearchOptimization」も大きくなります。

Apple Mobile Search Optimizationの取り組みは、通常のSEOよりもモバイルユーザーによるアプリの発見にはるかに大きな影響を及ぼします。

生まれたばかりのAMSO業界へようこそ。

悪いニュースは、これらすべての機能の実装には、Appleの多くの新しいテクノロジーと古いテクノロジーの拡張が含まれ、これらの要素の組み合わせが混乱を招く可能性があることです。 このシリーズの目標は、さまざまな部分をウォークスルーし、それらがどのように実装されるかを明確にすることです。 基本的なものから始めて、それに基づいて構築しましょう。

開発者向けのiOS9スポットライト検索の謎を解き明かす

このシリーズをサポートするために、全体を通して参照できる簡単なアプリを作成しました。 プロジェクトはここで見つけることができます:https://github.com/rwforsythe/iOS9-Search。 このシリーズが検索ツールキットの他の要素をカバーし続けるので、それはまた更新されます。

財団:CoreSpotlightフレームワーク

このフレームワークはiOS9で完全に新しく、ユーザーが発見できるようにアイテムをiPhoneのローカル検索インデックスに提供できます。 たとえば、iOS 9より前は、カレンダーなどの公式Appleアプリ内のコンテンツのみがSpotlight検索で見つかりました。 現在、CoreSpotlightフレームワークを介してカレンダーイベントを公開するアプリは、SpotlightSearchやSiriを介して見つけることができます。

ここでは個人情報に焦点を当てていることに注意してください。 個人のカレンダーイベントが別の電話のユーザーに表示されないようにする必要があります。 Appleは、CoreSpotlightフレームワークが各人の電話のプライベートインデックスと排他的に相互作用することを非常に明確にしています。 CoreSpotlight APIを使用して、電話機自体のインデックスの外部にコンテンツを公開することはできません。

これは、CoreSpotlightを使用してすでに公開されている情報にインデックスを付けることができないという意味ではありません。 CoreSpotlightを使用してクラウドから情報を取得し、それを電話の検索インデックスに配置することは確かに可能です。 個人情報と機密情報がCoreSpotlightで索引付けされている場合、それが機密のままであるということは、Appleからの単なる保証です。

フレームワークは2つの部分で構成されます。アプリが各アイテムを詳細に記述できるようにするCSSearchableItemAttributeSetオブジェクトと、アイテムに一意のIDを与えるために使用されるCSSearchableItemオブジェクトです。 各Spotlightエントリは、これらのオブジェクトのペアで構成されています。 1つではなく2つのオブジェクトを使用する理由は、 CSSearchableItemAttributeSetオブジェクトが異なる種類の検索インタラクション(後述)に使用されるためです。

基本的なことはとても簡単です。

サンプルコードを参照している場合、CoreSpotlightの設定はAppDelegateで行われます。

 … @import CoreSpotlight; @import MobileCoreServices; …

これらの2つのモジュールは、新しい機能に必要です。

デモアプリを簡単にするために、 application:didFinishLaunchingWithOptions:メソッドを使用して、CoreSpotlightを設定するための専用メソッドを呼び出します。

 if ([CSSearchableItemAttributeSet class]) [self setUpCoreSpotlight]; //Check for iOS version that supports CoreSpotlight API

setUpCoreSpotlightメソッドに移り、 CSSearchableItemAttributeSetオブジェクトを作成してプロセスを開始します。

 CSSearchableItemAttributeSet * attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeItem];

コンテンツタイプは、アイテムが検索アルゴリズムによって処理される一般的な方法を管理することになっているため、重要です。 「想定」は、Appleによって十分に文書化されていない領域であるため、有効な言葉です。 選択できるアイテムタイプ(画像タイプ、ビデオタイプ、オーディオタイプ、連絡先タイプ)のメニューは豊富ですが、ユーザーエクスペリエンスにどのような影響があるかを判断するには、試行錯誤が必要です。 一部のタイプは、検索結果に表示されるときに他のタイプよりも多くのテキストコンテンツを表示するように見えます。 また、サムネイル画像が結果と一緒に表示されるかどうかにも影響を与える可能性があります。 kUTTypeItemは開始するのに最適な場所です。

次に、オブジェクトについて詳しく説明します。

 attributeSet.displayName = @"A Christmas Carol"; attributeSet.title = @"A Christmas Carol By Charles Dickens"; //Sounds similar to displayName but is not displayed to user attributeSet.contentDescription = @"Who would dare to say “Bah! Humbug” after reading A Christmas Carol? Charles Dickens wrote the novella in just six weeks before it was first published on December 19 1843 but his morality tale about a bitter old miser named Ebenezer Scrooge lives on to this day as a reminder of the importance of the Christmas spirit."; attributeSet.keywords = @[@"A Christmas Carol", @"Charles Dickens", @"Victorian Literature"]; UIImage *image = [UIImage imageNamed:@"CC-Cover"]; NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)]; attributeSet.thumbnailData = imageData;

画像や動画などのメディアタイプに固有の、可能なプロパティはたくさんあります。 おそらくより多くの情報の方が良いでしょうが、実際に使用されている情報や検索結果に表示されている情報を判断するには、試行錯誤が必要です。 たとえば、執筆時点では、attributeSetに星評価データが含まれている場合でも、特定のインデックスアイテムの星評価は表示されていないようです。

ほとんどのテキストプロパティは検索クエリに含まれているため、titleプロパティが表示されていなくても、検索によってテキストを見つけることができます。 したがって、keywordsプロパティがtitleプロパティと根本的にどのように異なるかは完全には明らかではありません。

詳細については、Appleのドキュメントを参照してください:developer.apple.com

最後のステップは、 CSSearchableItemAttributeSetCSSearchableItemと一緒にパッケージ化し、それをインデックスに登録することです。

 CSSearchableItem *item1 = [[CSSearchableItem alloc] initWithUniqueIdentifier:@”https://www.notestream.com/streams/564159e4e5c24” domainIdentifier:@"notestream.com" attributeSet:attributeSet];

ここに2つの新しいものがあります。 domainIdentifierプロパティを使用すると、バッチ操作のためにアイテムをグループ化できます。 たとえば、カレンダーアプリの@ "meetingItem"と@"reminderItem"を使用すると、ある種類のすべてのSpotlightエントリを削除し、他の種類は残しておくことができます。

uniqueIdentifierプロパティには、果たすべきより重要な役割があります。 まず、ユーザーがCoreSpotlightインデックスのアイテムをクリックすると、アプリに戻されます(後で説明します)。 次に、検索インフラストラクチャの他の要素を使用する場合にこれがどのように見えるかについて、Appleからの推奨事項があります。 今のところ、このアイテムを一意に表すURLである文字列を使用します。 技術的には、このプロパティは、アイテムに固有である限り、任意の文字列にすることができます。

最後のステップ:作成したアイテムを実際のインデックスにプッシュします。

 [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:@[item1, item2, item3] completionHandler: ^(NSError * __nullable error) { if (!error) NSLog(@"Search item(s) journaled for indexing."); }];

ここで行うべきいくつかのポイント:

  1. このメソッドはオブジェクトの配列を取ります(インデックスを作成するデータが多い場合にプロセスをバッチ処理するために使用できる他のメソッドがあります)。

  2. この方法では、実際にはインデックス作成プロセスが完了しないことを理解することが重要です。 完了ハンドラーは、検索項目が索引付けのためにキューに入れられた場合にのみ呼び出されます。 CSSearchableIndexDelegateを使用して、インデックス作成プロセス自体が何らかの理由で失敗し、アプリがその状況を処理する必要があるシナリオを処理します。

おめでとうございます。携帯電話のCoreSpotlight検索インデックスにアイテムを追加しました。

iOS9での検索のしくみ

当然のことながら、Appleは検索アルゴリズムを胸の近くに置いているので、サンプルアプリをインストールして、キーワードを試してみる価値があります。 たとえば、Appleは、ユーザーが各文字を入力したときに非常に異なる結果を与えることで、提示された結果を最大化していることがすぐに明らかになります。

原則として、2、3文字入力しただけで、より適切と思われる結果が表示されるようです。 ユーザーがより多くの文字を入力すると、それらの初期の結果は削除され、代わりに他のもの(当初は可能性が低いと推定された)が表示されます。

より一般的には、Appleは彼らのアルゴリズムの下でランキングを改善する方法について言うことがほんの少ししかありません。 このページには、Appleの推奨事項が含まれています。検索結果を強化する

Appleのドキュメントからの重要なポイントの1つは、アプリが複数の検索テクノロジーを使用してコンテンツのインデックスを作成すると、ランキングが向上することです。 次の記事では、これらのテクノロジーのもう1つについて詳しく説明します。 一方、ユーザーが検索結果をクリックしたときのシナリオを処理するためのコードを実装する必要があります。

ユーザーがクリックしたとき

インデックスに潜在的な検索結果を入力するコードを作成しましたが、ユーザーが結果をクリックするとどうなりますか? 答えは、CoreSpotlightがUIApplicationDelegateプロトコルからapplication:continueUserActivity:restorationHandler:メソッドを借用していることです。 これは元々、ユーザーアクティビティをデバイスからデバイスに渡すことを可能にするハンドオフメカニズムのためにiOS 8で導入されました(たとえば、ユーザーはiWatchでWeb URLを表示し、ハンドオフを使用してiPhone Safariブラウザーで取得し、最終的に表示します)彼らがオフィスに着いたとき、彼らのMacで。)

最初の課題は、メソッドがHandoffアクティビティのために呼び出されたのか、SpotlightSearchから呼び出されたのかを判断することです。 アクティビティパラメータのactivityTypeプロパティで通知されますが、コードがiOS 8で実行される可能性がある場合は、その場合のクラッシュを回避する必要があります。

いくつかの簡単なコードがここにどのように見えるかを次に示します。

 - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)activity restorationHandler:(void (^)(NSArray *))restorationHandler { NSString * valueCSSearchableItemActionType; BOOL wasHandled = NO; if ([CSSearchableItemAttributeSet class]) //iOS 9 { valueCSSearchableItemActionType = CSSearchableItemActionType; } else { // iOS 8 – This method was introduced in iOS 8, so iOS 7 is not a possible scenario valueCSSearchableItemActionType = @"not supported"; } if ([activity.activityType isEqual: valueCSSearchableItemActionType]) { // Invoked via CoreSpotlight, we can assume iOS 9 from now on… NSString * activityIdentifier = [activity.userInfo valueForKey:CSSearchableItemActivityIdentifier]; wasHandled = YES; NSLog(@"Continuing user activity %@", activityIdentifier); } else { //the app was launched via Handoff protocol //or with a Universal Link } return wasHandled; }

コードの行に注意してください。

 NSString * activityIdentifier = [activity.userInfo valueForKey:CSSearchableItemActivityIdentifier];

これにより、 CSSearchableItemオブジェクトが作成されたときにスポットライトインデックスに配置された一意の識別子が抽出されます。 当然、アプリはこの一意の識別子を使用して、ユーザーが検索インデックスから選択したコンテンツをユーザーに提示する必要があります。 ここでは簡単にするために、一意の識別子をNSLogするだけです。

要約

これまで、iOS9の検索機能の一部のみを検討してきました。 電話のSpotlight検索インデックスに、ドキュメント、カレンダーアイテム、連絡先など、ユーザーが役立つと思われるものを読み込むために必要なコア機能を実行しました。 ユーザーが何かを検索し、アプリの結果を確認してクリックすると、アプリはリクエストを処理し、ユーザーに適切なアイテムを表示できるようになります。

まだ議論していないのは、Appleが構築しているパブリックインデックスに関連するテクノロジーです。 このインデックスは、ユーザーが携帯電話にインストールされていなくても、アプリ内のコンテンツを検索できるようにすることを目的としています。 次の投稿でそれに取り組みます。