civil-and-structural-engineering
Using the Ios Core Spotlight Api to Enable Content Search in Your App
Table of Contents
Introduction
Modern mobile users expect instant access to information. Integrating system‑level search into your iOS app dramatically reduces friction, allowing users to find content without opening your app first. The Core Spotlight API is Apple’s built‑in framework for indexing app content into the device’s global Spotlight search. When a user searches from the Home screen or within the Search view, your app’s indexed items appear alongside results from Mail, Messages, and other system apps. This article provides a comprehensive, production‑ready guide to implementing Core Spotlight, covering everything from basic indexing to deep linking and performance tuning.
Understanding Core Spotlight and Its Benefits
Core Spotlight is a lightweight, privacy‑friendly indexing system. It lives entirely on‑device – no data leaves the user’s phone unless you explicitly use CloudKit. This makes it ideal for personal content such as notes, contacts, documents, or any user‑generated data. The primary benefits include:
- Increased engagement – Users discover content they might have forgotten, boosting repeat usage.
- Seamless navigation – Tapping a search result can open your app directly to the relevant screen.
- Offline capability – Indexed items remain searchable even without internet connectivity.
- Low implementation cost – The API is small, well‑documented, and integrates easily with existing data models.
Core Spotlight works alongside NSUserActivity indexing, but for static or frequently updated content, direct CSSearchableItem indexing gives you finer control.
Prerequisites and Setup
Before writing code, ensure your project is configured correctly:
- Your app must target iOS 9 or later (the API debuted with iOS 9).
- Enable Core Spotlight capability in Xcode – under Signing & Capabilities add the “Core Spotlight” entitlement. This is often automatically included when importing the framework.
- Import the Core Spotlight framework and MobileCoreServices (for type identifiers):
import CoreSpotlightandimport MobileCoreServices.
No additional server configuration or user permission is needed. Indexing happens asynchronously in the background.
Creating and Indexing Searchable Items
The core of Core Spotlight is the CSSearchableItem object. Each item consists of:
- A unique identifier (e.g.,
com.yourapp.content.123) – used later to handle selection or updates. - An optional domain identifier – groups related items (e.g.,
com.yourapp.notes). - An attribute set (
CSSearchableItemAttributeSet) – describes the content with properties liketitle,contentDescription,keywords,thumbnailData, and more.
Here’s a complete Swift example that indexes a single note:
import CoreSpotlight
import MobileCoreServices
func indexNote(note: Note) {
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)
attributeSet.title = note.title
attributeSet.contentDescription = note.body
attributeSet.keywords = [note.title] + note.tags
if let imageData = note.thumbnail?.pngData() {
attributeSet.thumbnailData = imageData
}
let item = CSSearchableItem(
uniqueIdentifier: "com.yourapp.note.\(note.id)",
domainIdentifier: "com.yourapp.notes",
attributeSet: attributeSet
)
// Optionally set expiration date (default is one month)
// item.expirationDate = Date.distantFuture
CSSearchableIndex.default().indexSearchableItems([item]) { error in
if let error = error {
print("Indexing error: \(error.localizedDescription)")
} else {
print("Note indexed successfully.")
}
}
}
Attribute Set Properties
The CSSearchableItemAttributeSet inherits from NSObject and offers dozens of properties. For most apps the following are essential:
title– Short, descriptive text that appears prominently.contentDescription– A longer snippet shown below the title.keywords– Array ofStringfor alternate search terms.thumbnailDataorthumbnailURL– Visual preview.relatedUniqueIdentifier– Links items together (e.g., parent‑child notes).
For media content, use type‑specific properties like artist, album, or duration.
Updating and Deleting Indexed Content
When your app’s content changes, you must keep the index in sync. Use the same CSSearchableIndex methods:
Updating an Item
Call indexSearchableItems with the same unique identifier – the API automatically replaces the old entry.
Deleting Items
Use deleteSearchableItems(withIdentifiers:) or deleteSearchableItems(withDomainIdentifiers:) to remove stale content:
CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: ["com.yourapp.note.123"]) { error in
// handle
}
Batch operations are efficient: pass arrays to indexSearchableItems or deleteSearchableItems. For a full reset, use deleteAllSearchableItems (rarely needed).
Handling User Activity and Deep Linking
When a user taps a Spotlight result, your app receives a call through the NSUserActivity continuation. Implement the following delegate method in your AppDelegate or SceneDelegate:
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if userActivity.activityType == CSSearchableItemActionType {
if let userInfo = userActivity.userInfo,
let identifier = userInfo[CSSearchableItemActivityIdentifier] as? String {
// Navigate to the item with this identifier
navigateToContent(identifier: identifier)
return true
}
}
return false
}
Restoring State
For a smoother experience, also implement application(_:willContinueUserActivityWithType:) to show a loading state. In scene‑based apps (iOS 13+), use the UISceneDelegate method scene(_:continue:).
Deep Linking with NSUserActivity
Core Spotlight also works with the NSUserActivity mechanism. If you already index activities via userActivity, you can add the isEligibleForSearch flag. However, for fine‑grained control over titles and descriptions, use CSSearchableItem directly.
Best Practices for Effective Indexing
Following these guidelines ensures your indexed content remains relevant and performant:
1. Index Only Meaningful Content
Don’t index every tiny piece of data. Focus on items users are likely to search for: recent documents, high‑value pages, or bookmarked content.
2. Set Proper Expiration Dates
By default, items expire after one month. For static content, set expirationDate = Date.distantFuture. For time‑sensitive data (e.g., event reminders), use a realistic date.
3. Use Domain Identifiers Wisely
Domain identifiers allow you to delete all items from a group at once. For example, if a user deletes a folder, call deleteSearchableItems(withDomainIdentifiers: ["com.yourapp.folder.456"]).
4. Provide Meaningful Keywords
Include synonyms, common misspellings, and alternative names. Avoid overstuffing; 5–10 well‑chosen keywords are enough.
5. Avoid Indexing Duplicate Content
If you duplicate items (e.g., the same title in different domains), users see confusing results. Deduplicate at the app level.
6. Batch Operations for Bulk Updates
When syncing many items (e.g., after a cloud restore), batch them into arrays of 50–100 to avoid blocking the main thread. Use indexSearchableItems with an array, not multiple single calls.
Performance and Battery Considerations
Core Spotlight runs a low‑priority background process. But poor implementation can drain battery or degrade system performance:
- Limit reindexing frequency – Only reindex when data actually changes, not on every app launch.
- Throttle large operations – Use
beginIndexBatchandendIndexBatch(available onCSSearchableIndex) for atomic updates. - Avoid heavy images –
thumbnailDatashould be small (e.g., 64×64 points, JPEG compressed). Large images increase memory pressure. - Use the default index –
CSSearchableIndex.default()is sufficient for almost all apps. Creating custom indexes is rarely needed.
Apple’s Core Spotlight documentation emphasises that indexing should be treated as “fire and forget” – do not synchronously wait for completion callbacks on the main thread.
Testing Core Spotlight Integration
Debugging Spotlight results can be tricky because they don’t always appear immediately. Follow this testing strategy:
- Simulator testing – Use iOS Simulator (iOS 15 or later). After indexing, wait a few seconds, then pull down the Home screen to search. Be aware that results may take longer in the Simulator.
- Device testing – Always test on a physical device. Spotlight indexing behaves more aggressively on real hardware.
- Reset the index – Use the Settings app: General → Spotlight Search → toggle your app off and on. This clears the index and forces a fresh start.
- Verify deletion – After deleting an item, ensure the old result no longer appears. Sometimes the system caches results; give it up to 30 seconds.
- Check the debug console – Enable
com.apple.CoreSpotlightlogging by passing-com.apple.CoreSpotlight LogLevel 7in Xcode’s scheme arguments.
A useful resource is WWDC 2015 “Introducing Core Spotlight”, which covers foundational concepts still applicable today.
Conclusion
The Core Spotlight API is a robust, underutilised tool that can transform how users interact with your app. By adding relevant, up‑to‑date content to the system’s search index, you provide a friction‑less path from search to content – boosting engagement and retention. Start small: index your most important content first, test thoroughly, and then expand to cover secondary items. Remember to keep your index clean, use unique identifiers consistently, and handle user activity callbacks gracefully. With the steps outlined in this article, you’re ready to deliver a first‑class search experience that feels native to iOS.
For further reading, consult the official Core Spotlight Framework Reference and the App Search Programming Guide.