日記エントリを Spotlight にインデックスさせたい。
(経緯:WWDC24:Support semantic search with Core Spotlight – long forgotten now…)
// インデックス作成
func searchableItem(from entry: DiaryEntry) -> CSSearchableItem {
let attributeSet = CSSearchableItemAttributeSet(contentType: UTType.content)
attributeSet.contentType = UTType.text.identifier
attributeSet.title = entry.title
attributeSet.textContent = entry.content
attributeSet.recordingDate = entry.date
let item = CSSearchableItem(
uniqueIdentifier: "\(entry.date.timeIntervalSince1970)",
domainIdentifier: domainIdentifier,
attributeSet: attributeSet
)
return item
}
let index = CSSearchableIndex(name: "example")
let items = diaryEntries.map { searchableItem(from: $0) }
do {
try await index.indexSearchableItems(items)
} catch {
// error handling
}// 検索
func buildQuery(with keywords: [String]) -> String {
// refer to:
// Searching for information in your app | Apple Developer Documentation
// https://developer.apple.com/documentation/corespotlight/searching-for-information-in-your-app
let perWordQueries: [String] = keywords.map { word in
let v = "\"*\(word)*\"c" //大文字小文字を無視
return "(title == \(v)) || (textContent == \(v)))"
}
return perWordQueries.count > 1
? "(" + perWordClauses.joined(separator: ") && (") + ")"
: perWordClauses.first ?? ""
}
let searchQuery = buildQuery(with: keywords)
let context = CSSearchQueryContext()
context.fetchAttributes = ["title", "textContent"]
let query = CSSearchQuery(
queryString: searchQuery,
queryContext: context
)
var results: [CSSearchableItem] = []
query.foundItemsHandler = { items in
// `items` is hit results
results += items
}
query.completionHandler = { error in
// completion handling
print(results)
}これでアプリ内からインデクスしたコンテンツに対して Spotlight 検索し、ヒットすることが確認できた。
参考
Adding your app’s content to Spotlight indexes | Apple Developer Documentation
Searching for information in your app | Apple Developer Documentation