Make your app content show on Spotlight

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 CoreSpotlightand it works as follows:

  1. It searches for files and other items on the device and indexes your app's content for searching;
  2. It indexes both local and online data to deliver fast, relevant results, streamlining information discovery;
  3. 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:

  1. First method: Using the AppShortcutsProvider.updateAppShortcutParameters() method;
  2. 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 list
    • BookDetailView - presents the details of a stored book
    • AddBookView - handles the addition of a new one
    • WebView - rendering the file
  • Model folder, collecting all the model files
    • Book - defines the book type
    • DataModel - data persisted using SwiftData
  • Manager folder
    • NavigationManager - handles navigation within the app
    • DataManager - handles the data operations
  • The BooksShelfBooksShelfSearchIntentApp file - the entry point of the app
  • Intents folder - collecting all files related to intents
    • BookEntity - handling the AppEntity for the Book model
    • OpenBookIntent - handling the AppIntent that allows opening a specific book
    • ShorcutsProviders - handling the AppShortcutsProvider conforming type that enables the invocation of the intents via vocal commands
    • SearchIntent - handling the AppIntent 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.

Performing your app actions with Siri through App Shortcuts Provider
Expose your app actions to Siri Make with the App Intents framework.

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 {
    ...
}
  1. Conform your AppEntity to  IndexedEntity : this protocol represents an AppEntity 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
    }
}
  1. Create an extension of the AppEntity .
  2. Create a computed var of type  CSSearchableItemAttributeSet named attributeSet: it will store the attributed set, the data to donate to Spotlight that will be used to make the item be found.
  3. Initialize it on the defaultAttributeSet - a custom attributes that improve search accuracy in Spotlight.
  4. Assign the title to the title property.
  5. 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])
    }
    
    ...
    
}
  1. Import CoreSpotlight framework.
  2. In the method createNewBook(book:) , right after having added the new book to your storage, call the indexAppEntities() method: it expects as parameter a collection of AppEntity 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.

0:00
/0:20

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.

0:00
/0:25
To test if the content has been correctly exposed to Spotlight, from the home of your iPhone, drag down on the screen, a search bar on your keyboard will appear as well as Siri Suggestions. Search for a stored book, it will appear in the suggestions; by tapping on it, you will be redirected to its detailed view inside your app.

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.

0:00
/0:42

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:

  1. Automatically - by using the updateAppShortcutParameters() method - if implementing vocal commands phrases;
  2. 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.