Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2024 AI & Machine LearningApp ServicesSwiftUI & UI Frameworks

WWDC24 · 11 min · AI & Machine Learning / App Services / SwiftUI & UI Frameworks

Support semantic search with Core Spotlight

Learn how to provide semantic search results in your app using Core Spotlight. Understand how to make your app’s content available in the user’s private, on-device index so people can search for items using natural language. We’ll also share how to optimize your app’s performance by scheduling indexing activities. To get the most out of this session, we recommend first checking out Core Spotlight documentation on the Apple Developer website.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 14 snippets

Creating CSSearchableItem swift · at 2:14 ↗
// Creating searchable items for donation


let item = CSSearchableItem(uniqueIdentifier: uniqueIdentifier, domainIdentifier: domainIdentifier, attributeSet: attributeSet)
Creating CSSearchableAttributeSet swift · at 2:28 ↗
// Creating searchable content for donation


let attributeSet = CSSearchableItemAttributeSet(contentType: UTType.text)
attributeSet.contentType = UTType.text.identifier
Searchable items with type swift · at 2:40 ↗
// 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 swift · at 3:31 ↗
// 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
        }
    }
}
Avoid overwriting existing attributes swift · at 3:56 ↗
// Make it an update to avoid overwriting existing attributes


item.isUpdate = true
Configure a query swift · at 7:19 ↗
// Configure a query


let queryContext = CSUserQueryContext()
queryContext.fetchAttributes = ["title", "contentDescription"]
Ranked results swift · at 7:33 ↗
// Ranked results


queryContext.enableRankedResults = true
queryContext.maxRankedResultCount = 2
Suggestions swift · at 7:47 ↗
// Suggestions


queryContext.maxSuggestionCount = 4
Filter queries swift · at 7:55 ↗
// Filter queries


queryContext.filterQueries = ["contentTypeTree=\"public.image\""]
Query for searchable items and suggestions swift · at 8:23 ↗
// 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 swift · at 8:40 ↗
// Suggestions


suggestion.localizedAttributedSuggestion
Preparing for queries swift · at 8:56 ↗
// Preparing for queries


CSUserQuery.prepare
CSUserQuery.prepareWithProtectionClasses
Set the lastUsedDate swift · at 9:50 ↗
// 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 swift · at 10:00 ↗
// 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)

Resources