Skip to content

Core Spotlight & NSUserActivity ​

Complete reference for Core Spotlight framework and NSUserActivity — make app content discoverable in Spotlight search, enable Siri predictions, and support Handoff.

When to Use ​

  • Index app content (documents, notes, orders, messages) for Spotlight
  • Use NSUserActivity for Handoff or Siri predictions
  • Choose between CSSearchableItem, IndexedEntity, and NSUserActivity
  • Implement activity continuation from Spotlight results
  • Batch index for performance
  • Delete indexed content
  • Debug Spotlight search not finding app content
  • Integrate NSUserActivity with App Intents (appEntityIdentifier)
  • Configure semantic / on-device LLM search over indexed content with SearchableItemAttribute (iOS 27)

When to Use Each API ​

Use CaseApproach
User viewing specific screenNSUserActivity
Index all app contentCSSearchableItem
App Intents entity searchIndexedEntity
Handoff between devicesNSUserActivity
Background content indexingCSSearchableItem batch
LLM search over app content (OS 27)SpotlightSearchTool

Apple guidance: Use NSUserActivity for user-initiated activities (screens currently visible), not as a general indexing mechanism. For comprehensive content indexing, use Core Spotlight's CSSearchableItem.

Core Spotlight (CSSearchableItem) ​

Creating Searchable Items ​

swift
import CoreSpotlight
import UniformTypeIdentifiers

let attributes = CSSearchableItemAttributeSet(contentType: .item)
attributes.title = "Order #1234"
attributes.contentDescription = "Medium latte with oat milk"
attributes.keywords = ["coffee", "latte", "order"]
attributes.thumbnailData = imageData

let item = CSSearchableItem(
    uniqueIdentifier: order.id.uuidString,
    domainIdentifier: "orders",
    attributeSet: attributes
)

CSSearchableIndex.default().indexSearchableItems([item])

Batch Indexing ​

Always batch operations for performance:

swift
// ✅ GOOD: Batch index
let items = orders.map { $0.asSearchableItem() }
CSSearchableIndex.default().indexSearchableItems(items)

// ❌ BAD: Index one at a time
for order in orders {
    CSSearchableIndex.default().indexSearchableItems([order.asSearchableItem()])
}

NSUserActivity ​

Mark important screens for prediction and search:

swift
func viewOrder(_ order: Order) {
    let activity = NSUserActivity(activityType: "com.app.viewOrder")
    activity.title = order.coffeeName
    activity.isEligibleForSearch = true
    activity.isEligibleForPrediction = true
    activity.persistentIdentifier = order.id.uuidString

    // Connect to App Intents — EntityIdentifier, not a raw String (iOS 18.2+)
    activity.appEntityIdentifier = EntityIdentifier(for: OrderEntity.self, identifier: order.id)

    activity.becomeCurrent()
    self.userActivity = activity
}

App Intents Integration ​

Connect NSUserActivity and Core Spotlight to App Intents:

swift
// NSUserActivity → App Intent
activity.appEntityIdentifier = EntityIdentifier(for: OrderEntity.self, identifier: order.id)

// Core Spotlight → App Intent
let item = CSSearchableItem(appEntity: orderEntity)

Benefits:

  • Automatic "Find" actions in Shortcuts
  • Direct entity results in Spotlight search
  • Automatic Siri suggestions based on app entities

SpotlightSearchTool (OS 27) ​

SpotlightSearchTool (in the CoreSpotlight + FoundationModels cross-import overlay) lets a LanguageModelSession search your app's Core Spotlight index for grounded responses — with configurable sources, guidance profiles, contact resolution, custom pipeline stages, and streaming results for UI. The full API surface lives in the skill itself.

Released under the MIT License