Presenters: Jennifer Moore, Spotlight Engineer
Link: https://developer.apple.com/wwdc24/10131
- Framework that allows your app to donate searchable content to Spotlight
- Donate searchable content to Spotlight that represents what people will want to search
- Index items in a way that can be retrieved from a query
- Semantic search works best on text and media
- Use system-defined attributes when possible
// Creating searchable items for donation
let item = CSSearchableItem(uniqueIdentifier: uniqueIdentifier, domainIdentifier: domainIdentifier, attributeSet: attributeSet)
// Creating searchable content for donation
let attributeSet = CSSearchableItemAttributeSet(contentType: UTType.text)
attributeSet.contentType = UTType.text.identifier
// Searchable items with text
attributeSet.title
attributeSet.textContent
// Searchable items with media
attributeSet.contentType
attributeSet.contentURL
// Searchable items with links
attributeSet.contentURL
attributeSet.relatedUniqueIdentifier
// Batch indexing with client state
let index = CSSearchableIndex(name: "SpotlightSearchSample")
index.fetchLastClientState { state, error in
if state == nil {
index.beginBatch()
index.indexSearchableItems(items)
index.endIndexBatch(expectedClientState: state, newClientState: newState) { error in
}
}
}
// Make it an update to avoid overwriting existing attributes
item.isUpdate = true
// Configure a query
let queryContext = CSUserQueryContext()
queryContext.fetchAttributes = ["title", "contentDescription"]
// Ranked results
queryContext.enableRankedResults = true
queryContext.maxRankedResultCount = 2
// Suggestions
queryContext.maxSuggestionCount = 4
// Filter queries
queryContext.filterQueries = ["contentTypeTree=\"public.image\""]
// Query for searchable items and suggestions
let query = CSUserQuery(userQueryString: "windsurfing carmel", userQueryContext: queryContext)
for try await element in query.responses {
switch(element) {
case .item(let item):
self.items.append(item)
break
case .suggestion(let suggestion):
self.suggestions.append(suggestion)
break
}
}
// Suggestions
suggestion.localizedAttributedSuggestion
Models must be downloaded, so call this before search appears
// Preparing for queries
CSUserQuery.prepare
CSUserQuery.prepareWithProtectionClasses
// Set the lastUsedDate when the user interacts with the item
item.attributeSet.lastUsedDate = Date.now
item.isUpdate = true
// Interactions with items and suggestions from a query
query.userEngaged(item, visibleItems: visibleItems, interaction: CSUserQuery.UserInteractionKind.select)
query.userEngaged(suggestion, visibleSuggestions: visibleSuggestions, interaction: CSUserQuery.UserInteractionKind.select)