TipKitでアプリ内の案内を整えた後、次はアプリを開かなくてもホーム画面のSpotlight検索から直接データにたどり着けるようにしたいと考え、Core Spotlightに挑戦しました。
1. 保存するだけで自動的に検索対象になると思っていた
最初、SwiftDataやCoreDataにデータを保存すれば、それだけで自動的にSpotlight検索の対象になるものだと思い込んでいました。
let item = CSSearchableItem(uniqueIdentifier: id, domainIdentifier: "records", attributeSet: attributeSet)
実際にはCSSearchableItemを作成し、CSSearchableIndexへ明示的に登録する処理を自分で書く必要がありました。データの保存処理とSpotlightへの登録処理は別物で、登録処理を追加しない限りいつまでも検索には出てこないと気づくまで少し悩みました。
2. データを削除しても検索結果に残ってしまった
アプリ内でデータを削除する機能を実装していたのですが、削除したはずのデータがSpotlight検索の結果にまだ表示され続けるという不具合が発生しました。
発生した不具合:
アプリ内では削除済みなのにSpotlightの検索結果には残る
原因は、アプリ内のデータ削除処理にSpotlightのインデックスからの削除処理を追加し忘れていたことでした。deleteSearchableItemsを使って対応する項目を明示的に削除する処理を、データ削除の処理と必ずセットで呼ぶように直しました。
3. インデックス更新のタイミングを詰め込みすぎて動作が重くなった
データが更新されるたびに毎回すべてのデータをまとめて再インデックスする実装にしたところ、データ量が増えるにつれて保存操作のたびにアプリの動作が重くなる問題が出ました。
変更があった項目だけを差分でインデックス更新する処理に書き直し、初回起動時など特別な場合だけ全件をまとめてインデックスする形に分けたことで解決しました。何かのついでに全件処理を実行する実装は、データ量が増えた際に思わぬ負荷になると学びました。
4. 検索結果をタップした後の遷移先を作っていなかった
Spotlightの検索結果にアプリのデータが表示されるようになったので満足していたのですが、実際に検索結果をタップするとアプリのトップ画面が開くだけで、該当データの詳細画面には遷移しませんでした。
必要だった対応:
検索結果タップ時にuniqueIdentifierを受け取り、該当データの詳細画面へ遷移させる処理
userActivityやアプリ起動時のcontinueUserActivityでSpotlightからの遷移を受け取り、渡されたidentifierをもとに該当データの詳細画面まで導く処理を追加する必要がありました。検索結果に表示させることと、そこから正しい画面に遷移させることは別の実装だと痛感しました。
まとめ
- データの保存とSpotlightへの登録は別処理。
CSSearchableIndexへの明示的な登録が必要 - アプリ内でデータを削除する処理には、Spotlightのインデックスからの削除処理も必ずセットで入れる
- 全件の再インデックスは負荷が大きいので、通常は差分更新、特別な場合のみ全件更新と使い分ける
- 検索結果をタップした後の遷移先を、identifierをもとに実装しておく
検索結果に出ること自体は簡単でしたが、削除やタップ後の挙動まで含めて考えないと中途半端な機能になってしまうと実感した実装でした。
次は、Swift 6のStrict Concurrencyへの移行で分かったことをまとめます。
本記事は生成AI(Claude)を活用して執筆・編集しています。内容は実体験に基づき、執筆者本人が確認・監修しています。


コメント