<!--
{
  "documentType" : "article",
  "framework" : "CoreSpotlight",
  "identifier" : "/documentation/CoreSpotlight/adding-your-app-s-content-to-spotlight-indexes",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Adding your app’s content to Spotlight indexes"
}
-->

# Adding your app’s content to Spotlight indexes

Create a description for your app’s content and add it to a Spotlight
index to make it searchable.

## Overview

Search makes your app’s content easier to find, and plays a role both
inside your app and for features like Spotlight Search, Handoff,
Siri Suggestions, Reminders, and more. Making your content searchable
enhances the overall user experience of your app and improves the
discoverability of your content.

To help search find your content, create a private, on-device
index using the Core Spotlight framework and add your app’s data to
that index. Search works best when you index content that the person
cares about or interacts with directly, such as favorites, items they
purchased, messages they sent and received, and so on.

In addition to the content people can see in your UI, enable the
<doc://com.apple.documentation/documentation/Foundation/NSUserActivity/isEligibleForSearch>
property in relevant <doc://com.apple.documentation/documentation/Foundation/NSUserActivity>
objects that your app sends and receives. Enabling this property in
user-initiated activities adds those activities to the on-device
index and includes them in subsequent searches. For more information,
see <doc://com.apple.documentation/documentation/Foundation/NSUserActivity>.

### Assemble the item attributes

After you identify the content you want to index, collect some details
about it. Regardless of whether an item is a file or some part of your app’s data
structures, you provide metadata for that item to the Core Spotlight
index. You specify this metadata using a [`CSSearchableItemAttributeSet`](/documentation/CoreSpotlight/CSSearchableItemAttributeSet)
object, filling out only the properties that make sense for your content.
Attribute sets include data for specific types of content, such as
images and music. They also contain more general information about
an item, such as its name, who created it, the subject matter, and more.

Create the `CSSearchableItemAttributeSet` object and fill in as many
properties as makes sense for your data. Attribute sets store simple
data types such as strings, numbers, and dates to make the information
easier to search. The following example shows a method to index an
app-specific data type that manages a spreadsheet document. The code
retrieves data from the custom type to fill in the relevant attributes:

```swift
// Create an attribute set to describe an item.
func addSpreadsheetToIndex(_ item: MySpreadsheetType) { 
    // Assemble the metadata for the spreadsheet file.
    let attributeSet = CSSearchableItemAttributeSet(contentType: UTType.spreadsheet)
    attributeSet.title = item.title
    attributeSet.contentDescription = "Spreadsheet Document"
    attributeSet.thumbnailData = item.thumbnailImage
    attributeSet.contentURL = item.fileURL

    // Create the searchable item.
    let searchableItem = CSSearchableItem(uniqueIdentifier: item.identifier, domainIdentifier: nil, attributeSet: attributeSet)
    
    // Add the item to the index.
}
```

The [`CSSearchableItemAttributeSet`](/documentation/CoreSpotlight/CSSearchableItemAttributeSet) class supports making a phone call
or getting directions to a location associated with an item. To enable
these features, set the item’s [`supportsPhoneCall`](/documentation/CoreSpotlight/CSSearchableItemAttributeSet/supportsPhoneCall)
or [`supportsNavigation`](/documentation/CoreSpotlight/CSSearchableItemAttributeSet/supportsNavigation) property to `1`
and fill in the relevant phone number or latitude and longitude information.
Only enable these actions when it’s appropriate and they represent
a primary action someone is likely to take. For example, it makes
sense to let someone call a business, but it doesn’t make sense to
let someone call a phone number that appears on a research paper.

### Create a searchable item to find your content later

With the attributes you collect for each item, create a [`CSSearchableItem`](/documentation/CoreSpotlight/CSSearchableItem)
to pass to the indexing system. For each searchable item, specify these details:

- A unique identifier string for locating the item in your app’s data structures
- The attribute set with the item’s metadata
- An optional string that specifies the domain or owner of the item.

Create searchable items as soon as you have the information to do so.
When someone creates a new item in your app, create a searchable item
for it immediately and add it to the index. When someone changes the title
of an item or other details, update the attributes and add it to the
index again. It’s very important to keep your app’s indexes up to date
so that searches return current information. People are more likely to
engage with your app if it returns good search results. A high level of
engagement also helps increase the ranking of your searchable items.

The following code builds on the previous example by creating a searchable
item for a custom app data structure. The code uses data from the data item itself
to fill in various attributes.

```swift
// Create an attribute set to describe an item.
func addSpreadsheetToIndex(_ item: MySpreadsheetType) {
    // Assemble the metadata for the spreadsheet file.
    let attributeSet = CSSearchableItemAttributeSet(contentType: UTType.spreadsheet)
    attributeSet.title = item.title
    attributeSet.contentDescription = "Spreadsheet Document"
    attributeSet.thumbnailData = item.thumbnailImage
    attributeSet.contentURL = item.fileURL

    // Create the searchable item.
    let searchableItem = CSSearchableItem(uniqueIdentifier: item.identifier, domainIdentifier: nil, attributeSet: attributeSet)
         
    // Add the item to the index.
}
```

If you expect an item to exist for an extended period of time, set an
appropriate value in the item’s [`expirationDate`](/documentation/CoreSpotlight/CSSearchableItem/expirationDate)
property. The system automatically expires items after a period of time,
so setting an expiration date causes the system to preserve the item
until the date you specify. If the person deletes the original data from your
app, remove the associated item from the index.

### Add items to a searchable index

To make your items appear in search results, add them to a [`CSSearchableIndex`](/documentation/CoreSpotlight/CSSearchableIndex)
object. Indexes store your app-specific data and remain on the device.
You can create multiple indexes for your app, and might do so to
protect someone’s personal information. For example, a music
app might place the general catalog of songs in the app’s primary index and
someone’s private playlists in a separate index.

When indexing your app’s content, use a named index. If you need to index more
sensitive data, such as someone’s contact information, create a more secure
index using the [`init(name:protectionClass:)`](/documentation/CoreSpotlight/CSSearchableIndex/init(name:protectionClass:)) method. The
following example creates a named index for the app’s main content and a
second index for content that requires extra security:

```swift
// Get the app's main index.
let mainIndex = CSSearchableIndex(name:"MainAppIndex")

// Create an encrypted index.
let secureIndex = CSSearchableIndex(name:"SecureIndex", protectionClass:.complete)
```

> Note: Use the ``doc://com.apple.corespotlight/documentation/CoreSpotlight/CSSearchableIndex/default()`` index only for prototyping and testing
> your code. Don’t use it to store content in the production version of your app.

To add new items to an index, or to update items already in an index,
call the [`indexSearchableItems(_:completionHandler:)`](/documentation/CoreSpotlight/CSSearchableIndex/indexSearchableItems(_:completionHandler:))
method of that index. The method incorporates the items asynchronously
into the index and notifies you when the work is done. Typically, you submit
items only when they change, but you might also submit items to extend their
expiration date.

```swift
secureIndex.indexSearchableItems([item]) { error in
    if error != nil {
        print(error?.localizedDescription)
    } else {
        print("Item indexed.")
    }
}
```

> Important: Provide a reindexing app extension to keep the index up
> to date even when your app isn’t running. For more information, see
> <doc://com.apple.corespotlight/documentation/CoreSpotlight/regenerating-your-app-s-indexes-on-demand>.

### Add multiple items to the index in batches

When adding or updating large numbers of items, consider breaking those
updates into multiple batches. Batch updates make it easier for your
code to recover from errors or crashes that happen during the indexing
process. The system waits for you to specify your searchable items and
end the batch update before it begins indexing the items. If an error
occurs, the metadata you add to the batch lets you determine the extent
of the indexing progress, and where the error occurred.

The following example shows a function that indexes several items using
a batch update. You can specify any information you want for the client
data, but must limit the total size of it to 250 bytes. If any errors
occur during the batch update, you can call [`fetchLastClientState(completionHandler:)`](/documentation/CoreSpotlight/CSSearchableIndex/fetchLastClientState(completionHandler:))
to determine where to start indexing your content again.

```swift
func indexBatch(_ items: [CSSearchableItem]) {
    let index = CSSearchableIndex(name: "MyIndex")

    var clientData = Data()
    // Fill clientData with something to identify the current items.
        
    index.beginBatch()
    index.indexSearchableItems(items)
    index.endBatch(withClientState: clientData) { error in
        if error != nil {
            // Handle the error.
        } else {
            // Success
        }
    }
}
```

> Note: The ``doc://com.apple.corespotlight/documentation/CoreSpotlight/CSSearchableIndex/default()`` index doesn’t support batch
> operations.

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)