I'm working with SwiftData and trying to replicate behavior similar to what I used to do with CoreData, where I had an extension on NSManagedObjectContext that allowed me to fetch all stored objects, regardless of entity type.
In CoreData, I used this:
extension NSManagedObjectContext {
public func fetchDebugData() throws -> [DebugEntity] {
guard let entities = persistentStoreCoordinator?.managedObjectModel.entities else {
return []
}
return try entities.compactMap { entity -> DebugEntity? in
guard let entityName = entity.name else { return nil }
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let results = try fetch(fetchRequest)
let debugObjects = results.compactMap { object -> DebugObject? in
guard let managedObject = object as? NSManagedObject else { return nil }
let keysArray = Array(managedObject.entity.attributesByName.keys)
return DebugObject(
attributes: managedObject.dictionaryWithValues(forKeys: keysArray),
managedObject: managedObject
)
}
return DebugEntity(
entityName: entityName,
objects: debugObjects
)
}
}
}
public struct DebugEntity: Identifiable {
public let id = UUID()
public let entityName: String
public let objects: [DebugObject]
// MARK: - Initializer
public init(
entityName: String,
objects: [DebugObject]
) {
self.entityName = entityName
self.objects = objects
}
}
public struct DebugObject: Identifiable {
public let id = UUID()
public let attributes: [String: Any]
public let managedObject: NSManagedObject?
// MARK: - Initializer
public init(
attributes: [String: Any],
managedObject: NSManagedObject?
) {
self.attributes = attributes
self.managedObject = managedObject
}
}
I’m now using SwiftData with @Model types and the ModelContext, and I want to dynamically fetch all objects from the store at runtime, without manually specifying each type. I understand that SwiftData is designed to be more type-safe and less dynamic than CoreData, but is there any way to accomplish this without traversing through the raw SQLite file manually?
NSManagedObjectModelfrom a SwiftDataModelContainer.Schema, then read everything using CoreData.ModelContainer. You can reuse that if you declare a[any PersistentModel.Type]array, and you avoid having to specify all the types a second time.