#Spotlight検索とは・・・?
ホーム画面で下にスワイプしたりすると出るあれです。
入力欄にキーワードを入力すると、各アプリのコンテンツなどから、一致するものを探してもらえるので、横断的にアプリのコンテンツを検索できるので便利です。
今回は、このSpotlight検索に、自分のアプリのコンテンツを表示させる方法についての記事です。
TodayExtensionやリッチプッシュなどのように、追加で証明書などもいらず、簡単に実装できてアプリへの導線が増やせるので、やってみてはいかがでしょうか🤔
#実装方法
##1.準備
プロジェクトにMobileCoreServiceとCoreSpotlightのFrameworkを入れます。
##2.保存処理を実装する
今回は、例として映画の情報である以下のMovie構造体をSpotlight検索に保存してみましょう。
struct Movie {
/// 映画固有の識別番号
let id: Int = 0
/// 名前
let title: String = "スパイダーマン"
/// あらすじ
let summary: String = "平凡な少年、ピーター・パーカーは放射能汚染された蜘蛛に噛まれたことで、超人的な能力を得てしまう・・・"
/// 画像
let thumbnail: UIImage? = UIImage(named: "spider")
/// 役者名の配列
let actorNames: [String] = ["トビー・マグワイア", "キルスティン・ダンスト", "ジェームズ・フランコ"]
}
import Foundation
import MobileCoreService
import CoreSpotlight
final class SpotlightManager {
func save(_ movie: Movie) {
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeData as String)
// ①タイトル
attributeSet.title = movie.title
// ②説明文
attributeSet.contentDescription = movie.summary
// ③画像
attributeSet.thumbnailData = movie.thumbnail.pngData()
// キーワード(表示されないが、タイトルや説明文に入ってない文言をここに入れておけば、検索した時に引っかかるようになる)
attributeSet.keywords = movie.actorNames
/*
uniqueIdentifierはAppDelegateで取り出すことができるので、
Spotlight検索経由でアプリを開いた時のためのURLスキームを入れておく
*/
let item = CSSearchableItem(
uniqueIdentifier: "my-app://open/movie?id=\(movie.id)",
domainIdentifier: "my-app",
attributeSet: attributeSet
)
CSSearchableIndex.default().indexSearchableItems([item], completionHandler: nil)
}
}
##3.起動時の処理を実装する
import CoreSpotlight
extension AppDelegate {
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) ->
Bool {
// Spotlightで開かれたかどうかをチェックする
switch userActivity.activityType {
case CSSearchableItemActionType:
return self.openApplicationFromSpotlight(userActivity)
default:
return false
}
}
private func openApplicationFromSpotlight(_ userActivity: NSUserActivity) -> Bool {
// userActivityからURLスキームを取得する
guard let urlScheme = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String else {
return false
}
// URLスキームを開いた時の処理を実装する
return true
}
}
##4.保存処理を作る
final class ViewController: UIViewController {
let spotlightManager = SpotlightManager()
private func show(_ movie: Movie) {
self.spotlightManager.save(movie)
}
}
##5.確認する
title
、description
、keyword
に設定した文字列を検索欄に入力すると表示されます。
以上で、ざっくりとした実装は以上です。
#おまけ
今回紹介した実装では、Spotlightに保存する画像をローカルのものを使用しましたが、URLで画像を取得して表示することも可能です。
例として画像キャッシュライブラリのNuke
を使用した方法を記載しておきます。
import Foundation
import MobileCoreService
import CoreSpotlight
import Nuke
func save(_ movie: Movie) {
ImagePipeline.shared.loadImage(
with: movie.thumbnailUrl,
progress: nil) { response, _ in
guard let thumbnail = response?.image else {
return
}
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeData as String)
attributeSet.title = movie.title
attributeSet.contentDescription = movie.summary
attributeSet.thumbnailData = thumbnail.pngData()
attributeSet.keywords = movie.actorNames
let item = CSSearchableItem(
uniqueIdentifier: "my-app://open/movie?id=\(movie.id)",
domainIdentifier: "my-app",
attributeSet: attributeSet
)
CSSearchableIndex.default().indexSearchableItems([item], completionHandler: nil)
}
}