Core Spotlight

RSS for tag

Index your app so users can search the content from Spotlight and Safari using Core Spotlight.

Posts under Core Spotlight tag

23 Posts

Post

Replies

Boosts

Views

Activity

How to index file based documents in Core Spotlight
I read this thread https://developer.apple.com/forums/thread/788979 thoroughly, but I’m still confused regarding indexing files content. I'm building a notes app where the notes are stored in files. A file can contain several notes (think paragraphs). Each note and the file document itself have a unique ID, all embedded in the file. So far so good, when the user opens a file in the app, I index all the notes in it using several CSSearchableItem, one for each note. Each CSSearchableItem gets a unique ID based on the note and file IDs. The notes are then visible in Spotlight search and when the user taps one of them, the app is called with a Spotlight activity and I present the note. I learned that I should create a CSImportExtension to allow the system to index files when app is not running. But the only method is update(_:forFileAt:), which allows to provide back to the system a single attributes set. How can I index the notes in a file as separate items? What happens if an iCloud document file is edited remotely and the app is not running, or is editing another file? Does the system detect it and run CSImportExtension on the file? All the notes and documents IDs are unique, and when the user duplicates the document file from within the app, new unique IDs are set in the duplicate file. But the user can also duplicate files outside the app, in which case the IDs remain the same in the duplicate file. How does Spotlight react to indexing two distinct items, with the same ID, but different 'contentURL'? What if I index a note from a file, and set the current contentURL of the file, and then the user moves the file. Next time when I index a note from this file, Spotlight will get an item with the same uniqueIdentifier but with a different contentURL. Won't this confuse the system? How to handle the case of deleted files: Unless a file is pending editing, the app doesn’t know it has been deleted, so it won’t remove the corresponding items from Spotlight. I should mention that I use a Core Data database, which stores the mapping from file document IDs to file URLs, actually to bookmarks, so I can track the files even if the user renames or moves them.
1
0
89
7h
onContinueUserActivity(CSSearchableItemActionType, perform) does not work on a SwiftUI macOS app
onContinueUserActivity(CSSearchableItemActionType, perform) works as expected on iOS when we search and select an item from Spotlight, but nothing happens when we do the same on a SwiftUI macOS app. var body: some Scene { WindowGroup { MyView() .onContinueUserActivity(CSSearchableItemActionType, perform: handleSpotlight) } } func handleSpotlight(_ userActivity: NSUserActivity) { // Is not called... } How can we respond to a user clicking a Spotlight result from our apps on macOS?
3
1
828
1w
How to find renamed app using old name in Spotlight?
We are planning on renaming our app. The new name is not like the current name. It will be renamed in the App Store as well as the App display name. Yet, we still want new and existing users to be able to find the app by using the old name in search/spotlight under iOS. A great example of this is entering Twitter to find the X app and it shows up in the App section in the Spotlight search. Are there any guidelines, settings, or tricks for doing this? Some have suggested adding a Spotlight search term but that will not have it show up in the App section I fear.
2
0
571
2w
AppIntents + CSSearchableItemAttributeSet: only displayName indexed?
On iOS 18, I'm trying to index documents in Spotlight using the new combination of AppIntents+IndexedEntity. However, I don't seem to be able to index the textContent of the document. Only the displayName seems to be indexed. As recommended, I start with the defaultAttributeSet: /// I call this function to index in Spotlight static func indexInSpotlight(document: Document) async { do { if let entity = document.toEntity { try await CSSearchableIndex.default().indexAppEntities([entity]) } } catch { DLog("Spotlight: could not index document: \(document.name ?? "")") } } /// This is the corresponding IndexedEntity with the attributeSet @available(iOS 18, *) extension DocumentEntity { var attributeSet: CSSearchableItemAttributeSet { let attributeSet = defaultAttributeSet attributeSet.title = title attributeSet.displayName = title attributeSet.textContent = docContent attributeSet.thumbnailData = thumbnailData attributeSet.kind = "document" attributeSet.creator = Constants.APP_NAME return attributeSet } } How can I have more that the displayName to be indexed? Thanks :-)
10
0
363
3w
Core Spotlight Semantic Search - still non-functional for 1+ year after WWDC24?
After more than a year since the announcement, I'm still unable to get this feature working properly and wondering if there are known issues or missing implementation details. Current Setup: Device: iPhone 16 Pro Max iOS: 26 beta 3 Development: Tested on both Xcode 16 and Xcode 26 Implementation: Following the official documentation examples The Problem: Semantic search simply doesn't work. Lexical search functions normally, but enabling semantic search produces identical results to having it disabled. It's as if the feature isn't actually processing. Error Output (Xcode 26): [QPNLU][qid=5] Error Domain=com.apple.SpotlightEmbedding.EmbeddingModelError Code=-8007 "Text embedding generation timeout (timeout=100ms)" [CSUserQuery][qid=5] got a nil / empty embedding data dictionary [CSUserQuery][qid=5] semanticQuery failed to generate, using "(false)" In Xcode 16, there are no error messages at all - the semantic search just silently fails. Missing Resources: The sample application mentioned during the WWDC24 presentation doesn't appear to have been released, which makes it difficult to verify if my implementation is correct. Would really appreciate any guidance or clarification on the current status of this feature. Has anyone in the community successfully implemented this?
1
3
874
Oct ’25
Tricky behavior of attribute names in CSSearchQuery, can't find documentation
I am wanting to not only surface my content in the system-level Spotlight search results but also to utilize the same index for my in-app search screen. The very few examples or tutorials I could find all craft a CSSearchQuery string using just the "title" attribute. I can't figure out where to look to understand how to search across other attributes. My most pressing need is to be able to perform a CSSearchQuery looking for a search term in the .htmlContentData attribute. If I search for this term in the system search field it returns results, so I know it's being indexed. However when I use a search query (in my app) like htmlContentData == "someSearchTerm" I get zero results. This frustration has led to some more general questions like: How do you know what attribute names are available to use in the search query? Is it just a string literal that's exactly the same as the CSSearchableItemAttributeSet property in Swift? e.g. property .htmlContentData is referred to as "htmlContentData" in the query string? Also, is there any way to just search across all attributes with CSSearchQuery? Obviously using the system Spotlight search (from Home Screen) you don't have to specify if you're searching the title or htmlContentData, it just finds it in either. Yet for CSSearchQuery I have to know up-front which fields I want to look in?
2
0
946
Oct ’25
[macOS] CoreSpotlight importer using CSImportExtension failing to index
I've been trying to add a CoreSpotlight indexer to my macOS application. The new template for the indexer uses the new appex CSImportExtension style importer. I've been following this -> https://developer.apple.com/documentation/corespotlight/csimportextension I changed the CSSupportedContentTypes in the Info.plist file to the correct file type uti. I added a dummy value into the attributes (see code below) - just setting contentDescription to 'noodle' (easy to search for) class ImportExtension: CSImportExtension {   override func update(_ attributes: CSSearchableItemAttributeSet, forFileAt: URL) throws {     // Add a dummy value, and see whether spotlight finds it     attributes.contentDescription = "noodle" } } I have a number of files on disk that match the uti (and can be found when I search by the file name) Yet, when I build and run my app, the a spotlight search for 'noodle' finds no results. Can anyone give me any advice? I cannot find any indication that the ImportExtension is called (although when I put a log message at the start of the update() call there's no message in the console which seems to suggest it's not being called). Is there any way of debugging this? Cheers and thanks -- Darren.
9
0
2.2k
Oct ’25
The Spotlight Import Extension does not allow to inspect document bundles to get the metadata for the spotlight
I've made working Spotlight Import Extension with in macOS 15.5 (24F74). mdimport confirm it's installed, and working. The problem is related to accessing data inside document bundles (package directory) class ImportExtension: CSImportExtension { override func update(_ attributes: CSSearchableItemAttributeSet, forFileAt url: URL) throws { // ERROR: The file "QuickSort.notepad" couldn't be opened because you don't have permission to view it. let fileWrapper = try FileWrapper(url: url) } } forFileAt url points to a bundle. In order to read the metadata the extension needs to load the bundle from url and access its content, however in the sandbox environment,t the url allows only access to the bundle directory itself in particular NSFileWrapper(url: url) fails with error "The file "name.extension" couldn't be opened because you don't have permission to view it.", and effectively prevent from providing useful metadata. Is there a way to access the Document Bundle content in order to read the metadata for Spotlight?
2
0
136
Sep ’25
Does Core Spotlight work with document-based apps?
I have a SwiftUI document-based app that for the sake of this discussion stores accounting information: chart of accounts, transactions, etc. Each document is backed by a SwiftData DB. I'd like to incorporate search into the app so that users can find transactions matching certain criteria, so I went to Core Spotlight. Indexing & search within the app seem to work well. The issue is that Spotlight APIs appear to be App based & not Document based. I can't find a way to separate Spotlight data by document. I've tried having each document maintain a UUID as a document-specific identifier and include the identifier in every CSSearchableItem. When performing a query I filter the results with CSUserQueryContext.filterQueries that filter by the document identifier. That works to limit results to the specific file for search operations. Index updates via CSSearchableIndexDelegate.reindex* methods seem to be App-centric. A user may have file #1 open, but the delegate is being asked to update CSSearchableItems for IDs in other files. Is there a proper way to use Spotlight for in-app search with a document-based app? Is there a way to keep Spotlight-indexed data local within the app & not make it available across the system? I.e. I'd like to search within the app only. System-level searches should not surface this data.
7
0
159
Jul ’25
Core Spotlight searching only for title
I just adding a way to donate my app's data to Core Spotlight using CSSearchableIndex, but I'm finding that spotlight is only searching for the title of the CSSearchableItem I create. I know the index is working, because it always finds the item through the title property, but nothing else. This is how I'm creating the CSSearchableItem: - (CSSearchableItem *) createSearchableItem { CSSearchableItemAttributeSet* attributeSet = [[CSSearchableItemAttributeSet alloc] initWithContentType: UTTypeText]; attributeSet.title = [self titleForIndex]; attributeSet.displayName = [self titleForIndex]; attributeSet.contentDescription = [self contentDescriptionForIndex]; attributeSet.thumbnailData = [self thumbnailDataForIndex]; attributeSet.textContent = [self contentDescriptionForIndex]; CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier: [self referenceURLString] domainIdentifier:@"com.cjournal.cjournal-Logs" attributeSet:attributeSet]; item.expirationDate = [NSDate distantFuture]; return item; } There's a lot of confusing tips around which say specifying the 'textContent' should work, and/or setting the displayName is essential, but none of these are working. Is there something I'm missing with my setup? Thanks.
0
0
97
Jun ’25
There were problems encountered during the development of core spotlight.
In IOS17 and IOS18, core spotlight can only match app contents by searching for the displayName, but cannot hit the contents by using keywords. Moreover, when matching the app content by searching for the "displayName", it requires inputting four consecutive characters to achieve a match.These issues did not occur in iOS 16. What is the reason for this? Here is my code. func addItemToIndex(_ item: QSpotlightItem) { let attributeSet = CSSearchableItemAttributeSet(contentType: .item) attributeSet.title = item.title attributeSet.displayName = item.title attributeSet.contentDescription = item.contentDescription attributeSet.keywords = item.keywords attributeSet.thumbnailData = item.thumbnailImage attributeSet.contactKeywords = item.keywords attributeSet.supportsNavigation = true let searchableItem = CSSearchableItem(uniqueIdentifier: item.id, domainIdentifier: "xxx", attributeSet: attributeSet) searchableItem.expirationDate = .distantFuture CSSearchableIndex.default().indexSearchableItems([searchableItem]) { error in if let error = error { } else { } } }
9
3
214
May ’25
In Core Spotlight, it requires four consecutive characters to index the content. Only through title or displayName can the content be indexed.
In Core Spotlight, one can only index content by using title or displayName, and it requires four consecutive characters for indexing. These situations occurred in iOS 17 and 18. In iOS 16, I could not only index content by title or displayName, but also by keyword. Moreover, there was no restriction of requiring four consecutive characters. I could index my app content by simply inputting one character. Here is my code.https://github.com/kritto1/corespotlight-bug-test/tree/main @available(iOS 14, *) func addItemToIndex(_ item: QSpotlightItem) { let attributeSet = CSSearchableItemAttributeSet(contentType: .item) attributeSet.title = item.title attributeSet.displayName = item.title attributeSet.contentDescription = item.contentDescription attributeSet.keywords = item.keywords attributeSet.thumbnailData = item.thumbnailImage attributeSet.contactKeywords = item.keywords attributeSet.supportsNavigation = true let searchableItem = CSSearchableItem(uniqueIdentifier: item.id, domainIdentifier: "com.qunar.iphone.spotlight", attributeSet: attributeSet) searchableItem.expirationDate = .distantFuture CSSearchableIndex.default().indexSearchableItems([searchableItem]) { error in if let error = error { } else { } } } @available(iOS 14, *) func addToSpotlightIndex() { let spotlightHotel = QSpotlightItem( id: "corespotlight_1", title: "查询酒店住宿", contentDescription: "", thumbnailImage: UIImage(named: "img2")?.pngData(), keywords: ["酒店", "住宿"] ) addItemToIndex(spotlightHotel) let spotlightFlight = QSpotlightItem( id: "corespotlight_2", title: "查询和预订机票", contentDescription: "", thumbnailImage: UIImage(named: "img2")?.pngData(), keywords: ["查询", "预订", "机票"] ) addItemToIndex(spotlightFlight) let spotlightSight = QSpotlightItem( id: "corespotlight_3", title: "查询预订门票", contentDescription: "", thumbnailImage: UIImage(named: "img2")?.pngData(), keywords: ["查询", "预订", "门票"] ) addItemToIndex(spotlightSight) }
1
1
119
Apr ’25
CSSearchableItemAttributeSet is missing recordingYear
I'd like to set the recordingYear in my Spotlight File Importer extension but the property is missing from CSSearchableItemAttributeSet e.g. in the resulting in mdls I'd like to see: kMDItemRecordingYear = 2008; This would allow me to search in Finder by the recording year criteria. There is a recordingDate property and I tried setting it to Date that only has a year but it didn't work. It just resulted in this: kMDItemRecordingDate = "2008-01-01 00:00:00 +0000";
0
0
56
Mar ’25
Core Spotlight "Summarization" Oddly Inconsistent
The new Core Spotlight APIs in 18.4 and aligned releases for using Apple Intelligence models to summarize messages sort of work? But I'd say in my testing that only about 80% of the requests I send to Spotlight come back to the delegate with summaries and the rest are never returned. No errors logged in the delegate methods. I can't figure out if there's a pattern. Before I dig apart my code, I'm wondering if anyone else here is using these brand-new APIs and has seen anything similar. It's odd because my code to submit to Spotlight to be summarized is the same for all of my entities but some just never seem to be returned.
2
0
162
Mar ’25
How to use core spotlight ?
Watched videos, blog post and downloaded their projects and there the core spot lights works accordingly. I copied code to an empty project and did the same as what they did but still is not working os: macOS and iOS on coredataobject I settled up a attribute to index for spotlight and in object it self I putted the attribute name in display name for spotlight. static let shared = PersistenceController() var spotlightDelegate: NSCoreDataCoreSpotlightDelegate? @MainActor static let preview: PersistenceController = { let result = PersistenceController(inMemory: true) let viewContext = result.container.viewContext for _ in 0..<10 { let newItem = Item(context: viewContext) newItem.timestamp = Date() } do { try viewContext.save() } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } return result }() let container: NSPersistentContainer init(inMemory: Bool = false) { container = NSPersistentContainer(name: "SpotLightSearchTest") if inMemory { container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") } container.loadPersistentStores(completionHandler: { [weak self] (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } if let description = self?.container.persistentStoreDescriptions.first { description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) description.type = NSSQLiteStoreType if let coordinator = self?.container.persistentStoreCoordinator { self?.spotlightDelegate = NSCoreDataCoreSpotlightDelegate( forStoreWith: description, coordinator: coordinator ) self?.spotlightDelegate?.startSpotlightIndexing() } } }) container.viewContext.automaticallyMergesChangesFromParent = true } } in my @main view struct SpotLightSearchTestApp: App { let persistenceController = PersistenceController.shared var body: some Scene { WindowGroup { ContentView() .environment(\.managedObjectContext, persistenceController.container.viewContext) .onContinueUserActivity(CSSearchableItemActionType) {_ in print("") } } } } onContinueUserActivity(CSSearchableItemActionType) {_ in print("") } never gets triggered. Sow What am I missing that they dont explain in the blog post or videos ?
3
0
202
Mar ’25
Spotlight services not fully stopping
I wish to have all spotlight services stopped on my MacBook, however with turning all options off in the settings and also the "Help Apple Improve Search" option, however the option turns back on whenever there is a restart on the laptop as well as background services running. How can I disable this permanently? I have tried to following as well: sudo mdutil -a -i off sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist sudo launchctl unload -w /System/Library/LaunchAgents/com.apple.metadata.mds.user.plist sudo rm /Library/Preferences/com.apple.spotlight.plist sudo launchctl disable system/com.apple.metadata.mds However with ps aux | grep -E "mds|Spotlight|corespotlightd" it still shows spotlight related services running: User1 73830 0.0 0.0 410741568 1680 s018 S+ 11:58am 0:00.00 grep -E mds|Spotlight|corespotlightd root 3170 0.0 0.0 410682288 4816 ?? Ss 20Jan25 4:28.08 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/mds_stores root 3168 0.0 0.0 427023376 14864 ?? Ss 20Jan25 33:53.97 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Support/mds User1 593 0.0 0.1 434378432 45456 ?? S 20Jan25 14:00.32 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/corespotlightd What else can I try in order to stop these and to stay shut off after turning my laptop on and off again?
1
0
297
Feb ’25
API to check Core Spotlight storage limit
There's a 128mb limit for donating items to core spotlight. As far as I understand, there's a warning that shows in the Xcode console when either approaching or hitting that limit. It would be great if there was an API to check the current status of available storage for QA purposes to see if we're either donating too much or can donate more. Thanks!
0
0
260
Jan ’25
Spotlight results | AppShortcut with AppEntity parameter vs CSSearchableItem.associateAppEntity
I've been exploring the Trails Sample App from this session at WWDC24. The app has a TrailEntity of type AppEntity which is leveraged in multiple places throughout the app, including: The GetTrailInfo App Intent with a trail parameter of type TrailEntity. A parameterized App Shortcut which calls the GetTrailInfo intent. The TrailDataManager's init calls updateSpotlightIndex(), which creates a CSSearchableItem for each Trail in the app, along with an associateAppEntity call linking the corresponding TrailEntity to each item that gets added to the CSSearchableIndex. If you build the app and search "trails" in Spotlight, the Trails Sample App section includes instances of TrailEntity as search results. But if you comment out the App Shortcut that takes a TrailEntity as a parameter and rebuild, there are no instances of TrailEntity in the search results. In both cases, the console prints [Spotlight] Trails indexed by Spotlight. Is this expected behavior? Why are the TrailEntity instances only appearing in Spotlight via the App Shortcut? Shouldn't the CSSearchableItem instances show up in Spotlight on their own regardless? If not, then what is the purpose of adopting Core Spotlight with App Entities? Does this add the app entities to the semantic index for "new Siri", even though they're not user facing in the Spotlight UI?
0
0
522
Jan ’25
Guidance Implementing IndexedEntity and CSSearchableItemAttributeSet
I am working to add Spotlight indexing for my app entities as discussed in WWDC24's video "What's New in App Intents". That video goes over the IndexedEntity protocol and the integration with Spotlight via CSSearchableItemAttributeSet. What I'm seeing though does not match the video. In the video, the presenter goes through the sort of progressive approach you can take to getting this data into Spotlight starting with the basics and then expanding to include more support depending on how much the developer wants to do. What I'm seeing is that if you conform to IndexedEntity, your entities will appear in Spotlight using the name derived from public var displayRepresentation: DisplayRepresentation So, that works. Name appears... BUT the next part of the video goes into how to expand your implementation with more metadata for Spotlight via CSSearchableItemAttributeSet. The issue I'm seeing is that once that's implemented, the items disappear from Spotlight, almost like that implementation is overriding the base implementation in a way that no longer functions. My expectation is that an item with custom attributes would use them in Spotlight as appropriate, not disappear from search, i.e. what's shown in the video should work. I've got a sample project here: https://hanchor.s3.amazonaws.com/misc/IndexingTest.zip To reproduce with the sample: Build and run. Indexing is setup in the init() method so it will just run. Go to Spotlight and search for 'Huntersblau', a string included in the content set. At this point you should see a result - good! Stop the app and go back and uncomment the var attributeSet: CSSearchableItemAttributeSet implementation in IndexingTestApp.swift. This will provide custom attributes to Spotlight. Repeat steps 1 and 2 - you'll see now, it no longer appears in the search results - when CSSearchableItemAttributeSet is implemented, the item drops out of Spotlight.
3
0
1.2k
Dec ’24