A dictionary of [A: [B]] efficiently, where A is an NSManagedObject representing the parent entity and [B] is an array of related objects, you’ll need a solution that minimizes looping and fetches while working with Core Data.
Approach 1: Fetch A Entities and Use NSManagedObject Relationships
// Assume we have a managed object context `context` let fetchRequest: NSFetchRequest<A> = A.fetchRequest() do { let aObjects = try context.fetch(fetchRequest) var result: [A: [B]] = [:] for a in aObjects { if let bObjects = a.bRelation?.allObjects as? [B] { result[a] = bObjects } } // Now `result` contains the grouped dictionary } catch { print("Failed to fetch A entities: \(error)") }
Core Data automatically manages the relationship, so accessing a.bRelation fetches related objects lazily (or eagerly if configured with a Fetch Request for preloading).
Approach 2: Use a Fetch Request with NSDictionaryResultType
let fetchRequest = NSFetchRequest<NSDictionary>(entityName: "B") fetchRequest.resultType = .dictionaryResultType // Assuming "aProperty" is the property that links B to A fetchRequest.propertiesToFetch = ["aProperty"] fetchRequest.propertiesToGroupBy = ["aProperty"] do { let groupedResults = try context.fetch(fetchRequest) var result: [A: [B]] = [:] for group in groupedResults { if let aObject = group["aProperty"] as? A { let bFetchRequest: NSFetchRequest<B> = B.fetchRequest() bFetchRequest.predicate = NSPredicate(format: "aProperty == %@", aObject) let bObjects = try context.fetch(bFetchRequest) result[aObject] = bObjects } } // `result` now contains the grouped dictionary } catch { print("Failed to group and fetch: \(error)") }
NSDictionaryResultType allows you to group objects in the database query itself, reducing the in-memory operation overhead.
Approach 3: Batch Fetch and Process Relationships
let batchSize = 500 // Fetch all B objects in batches let fetchRequest: NSFetchRequest<B> = B.fetchRequest() fetchRequest.fetchBatchSize = batchSize do { let bObjects = try context.fetch(fetchRequest) var result: [A: [B]] = [:] for b in bObjects { if let a = b.aRelation { // Assuming `aRelation` is the to-one relationship to A if result[a] == nil { result[a] = [] } result[a]?.append(b) } } // `result` now contains the grouped dictionary } catch { print("Failed to fetch B entities: \(error)") }