
Make your app content show on Spotlight
Learn how to index the content of your app to make it searchable via spotlight
Apple provides a way to search through the content stored on your device, enabling users to quickly locate apps, files, emails, contacts, and more using natural language queries. The framework that allows this capability is CoreSpotlight
and it works as follows:
- It searches for files and other items on the device and indexes your app's content for searching;
- It indexes both local and online data to deliver fast, relevant results, streamlining information discovery;
- It integrates with Siri and other system services to offer contextual suggestions from the web, news, and maps, resulting in a more intuitive and natural language style of interaction.
This capability doesn’t come by default; it’s up to the developer choosing which content should be exposed to the system. It’s a good practice to expose everything that can potentially be looked for in the app. Once indexed, it stays on your device, accessible only to the owner of the device, never shared with Apple.
There are two ways to expose your content to Spotlight and in this tutorial we are going to address both:
- First method: Using the
AppShortcutsProvider.updateAppShortcutParameters()
method; - Second method: Indexing your content via Core Spotlight APIs.
Before we start
We will use the following project to explore how to expose the content to Spotlight.
It’s a book library app that lets you keep track of your books on your shelf.
This starter project contains:
- View folder:
BooksListView
- shows the stored books as a listBookDetailView
- presents the details of a stored bookAddBookView
- handles the addition of a new oneWebView
- rendering the file
- Model folder, collecting all the model files
Book
- defines the book typeDataModel
- data persisted usingSwiftData
- Manager folder
NavigationManager
- handles navigation within the appDataManager
- handles the data operations
- The
BooksShelfBooksShelfSearchIntentApp
file - the entry point of the app - Intents folder - collecting all files related to intents
BookEntity
- handling theAppEntity
for theBook
modelOpenBookIntent
- handling theAppIntent
that allows opening a specific bookShorcutsProviders
- handling theAppShortcutsProvider
conforming type that enables the invocation of the intents via vocal commandsSearchIntent
- handling theAppIntent
that allows to perform research inside your app
The NavigationManager
and the shared Modelcontainer
are initialized at the app entry point. Launch the app and start storing your books; they will be needed to launch and test.
First method: Exposing your content to Spotlight with stored parameters
The first way of making your app content available for spotlight search. Open the starter project and do the following.
In the DataManager
class methods createNewBook(book:)
and deleteBook(book:)
, the following method is called:
BookShelfShortcutsProvider.updateAppShortcutParameters()
When using the AppShortcutsProvider.updateAppShortcutParameters()
, the system handles indexing automatically. When you update your app shortcut parameters, by implementing AppShortcutsProvider.updateAppShortcutParameters()
, the content you provide is automatically indexed and made available in Spotlight.
This means you don’t have to manually index the shortcuts using Core Spotlight APIs - the system takes care of it as long as you provide the necessary metadata in your parameters. Call updateAppShortcutParameters()
whenever you are updating your app stored content.
To learn more about this method, check our article about how to invoke your intents via vocal commands.

Second method: Indexing your content via Core Spotlight APIs
The second way of making the information in your app available for Spotlight is implementing the Core Spotlight APIs.
Step 1 - Start indexing the content of your app
<simple sentence>
struct BookEntity: IndexedEntity {
...
}
- Conform your
AppEntity
toIndexedEntity
: this protocol represents anAppEntity
with an attribute set that allows the system to perform structured indexing and queries of entities.
Step 2 - Create an extension of the AppEntity
Import CoreSpotlight
framework in the BookEntity.swift file.
import CoreSpotlight
Create an extension of the entity to compute the attibuted set.
// 1. Create an extension of the AppEntity
extension BookEntity {
// 2. Create a computed var storing the attributed set
var attributeSet: CSSearchableItemAttributeSet {
// 3. Initialize it on the defaultAttributeSet
let attributeSet = defaultAttributeSet
// 4. Assign the title
attributeSet.title = title
// 5. Return the attribute set
return attributeSet
}
}
- Create an extension of the
AppEntity
. - Create a computed var of type
CSSearchableItemAttributeSet
namedattributeSet
: it will store the attributed set, the data to donate to Spotlight that will be used to make the item be found. - Initialize it on the
defaultAttributeSet
- a custom attributes that improve search accuracy in Spotlight. - Assign the title to the title property.
- Return the variable.
Step 3 - Indexing the entities....
In the DataManager.swift file:
// 1.
import CoreSpotlight
class DataManager {
...
static func createNewBook(book: Book) async throws {
...
// 2. Index the entity into the system
try? await CSSearchableIndex.default().indexAppEntities([book.entity])
}
...
}
- Import
CoreSpotlight
framework. - In the method
createNewBook(book:)
, right after having added the new book to your storage, call theindexAppEntities()
method: it expects as parameter a collection ofAppEntity
which it will index into the system.
CSSearchableIndex.default()
is a shared searchable index object provided by the system. It’s the centralized place where all searchable content is stored.
Searching the content in the app via Spotlight
Step 4 - Updating the searchable index when deleting
Do not forget to update the list of the indexed entities every time a book gets deleted by calling the deleteAppEntities(identifiedBy:ofType:)
method.
class DataManager {
...
static func deleteBook(book: Book) async throws {
...
// Remove the corresponding entity from the indexed ones
try? await CSSearchableIndex.default().deleteAppEntities(identifiedBy: [book.id], ofType: BookEntity.self)
}
}
Removing outdated or deleted content ensures that users only see relevant results in Spotlight. It prevents confusion and maintains the integrity of your app's search experience.
Hiding the app data from Spotlight when needed
Starting from iOS 18.4 it’s also possible to control with hideInSpotlight
property whether the entity will be displayed in search results in the Spotlight UI.
extension BookEntity {
...
var hideInSpotlight: Bool {
return true
}
}
Add the property hideInSpotlight
to your custom AppEntity type to hide it from Spotlight search results
Add a computed variable called hideInSpotlight
of type Boolean
and return false
if you want to make the entity indexed for Spotlight or true
if you want to hide it. By default, the property is set on false.
Final Result
You can download the final version of the project here:
To recap, exposing the content of the app to Spotlight can be handled in 2 different ways:
- Automatically - by using the
updateAppShortcutParameters()
method - if implementing vocal commands phrases; - Manually - by implementing an indexing logic via
CoreSpotlight
APIs.
As you can see, whether you are relying on automatic exposure or manually indexing, if you want to enhance the user experience and streamline information retrieval, exposing your app's content to Spotlight should be a must-have feature.