I’m building an AppIntent Shortcut and want to perform fetch requests of my apps Core Data to feed the Shortcut with the data.
My Code
Core Data Handling:
class HomesHandler: NSObject, ObservableObject {
static let shared = HomesHandler()
let objectContext = PersistenceController.shared.container.viewContext
func fetchAllHomes() -> [Home] {
let request: NSFetchRequest<Home> = Home.fetchRequest()
// PERFORM FETCH
do {
return try objectContext.fetch(request)
} catch let error {
print("Error fetching Homes: \(error.localizedDescription)")
return []
}
}
}
AppIntent Code:
struct HomeIntentQuery: EntityPropertyQuery {
// Populates the list when the user taps on a parameter that accepts a Home.
func suggestedEntities() async throws -> [HomeIntentEntity] {
// Fetch All Homes
// Sorted by non-archived first
let allHomes = HomesHandler.shared.fetchAllHomes().sorted(by: { !$0.isArchived && $1.isArchived })
// Map Core Data to AppEntity
return allHomes.map { home in
HomeIntentEntity(id: home.id,
title: home.wrappedTitle,
isArchived: home.isArchived)
}
}
// …
Intent Entity to Core Data Bridge:
struct HomeIntentEntity: AppEntity, Identifiable {
// Required to conform to Identifiable
var id: UUID
// Properties mirrored from Core Data
@Property(title: "Title") var title: String
@Property(title: "Is Archived") var isArchived: Bool
// …
}
Core Data Persistence Controller:
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentContainer
// An initializer to load Core Data,
// optionally able to use an in-memory store.
init(inMemory: Bool = false) {
// Access actual Core Data file
container = NSPersistentContainer(name: "MeterStats")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Core Data Loading Error: \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
}
}
Problem
The problem I have is that the code crashes with a EXC_BREAKPOINT whenever the app is running in the background. Once the app is closed the fetch request just works fine. How can that be?
I’ve already tried to wrap the do try objectContext.fetch(request)
into objectContext.performAndWait
. Though, that leads to a crash inside the .sorted(by:)
when trying to access .isArchived
The strange thing is that this works perfectly fine at this great GitHub example by Alex Hay. He uses the same code to do the fetch request as well as the AppIntent code.
So, how do I have to handle fetch requests that are running inside AppIntents correctly?