Last active
November 21, 2025 07:35
-
-
Save juanarzola/131c81f2cdb438dc8114bb003b87eff2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SwiftData | |
| import CoreSpotlight | |
| import FetchDescriptorObserver | |
| import OSLog | |
| import AppIntents | |
| private let logger = Logger.spotlight | |
| // Initialize from a SwiftData PersistentModel | |
| protocol FromPersistentModel { | |
| associatedtype Model: PersistentModel | |
| init(persistentModel: Model) | |
| } | |
| extension ModelContainer { | |
| /// Observe changes to IndexedEntity's associated PersistentModel, using a FetchDescriptor. | |
| /// When they change, they are reindexed in Spotlight | |
| @MainActor | |
| func indexFoldersInSpotlight() async throws { | |
| try await FolderEntity.indexInSpotlight(.allFolders, from: self) | |
| } | |
| ... | |
| } | |
| // Extend `IndexedEntities` that can be initialized `FromPersistentModel` | |
| // to be indexable in Spotlight | |
| extension IndexedEntity where Self: FromPersistentModel { | |
| /// Invoke in a Task in your App to index in spotlight in the background | |
| @MainActor | |
| static func indexInSpotlight( | |
| _ descriptor: FetchDescriptor<Self.Model>, | |
| from modelContainer: ModelContainer) async throws | |
| { | |
| let observer = descriptor.makeObserver { models in | |
| /// Fetching and mapping happens in a background thread | |
| models.map { Self(persistentModel: $0) } | |
| } | |
| var errorCount = 0 | |
| for try await entities in observer | |
| .values(modelContainer) | |
| .debounce(for: .milliseconds(500)) { | |
| do { | |
| let spotlightIndex = CSSearchableIndex.default() | |
| try await spotlightIndex.deleteAppEntities(ofType: Self.self) | |
| try await spotlightIndex.indexAppEntities(entities) | |
| } catch { | |
| errorCount += 1 | |
| logger.error(""" | |
| \(#function): Indexing error #\(errorCount): | |
| \(error) | |
| """) | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment