Skip to content

Commit

Permalink
Fix a bug in model merging
Browse files Browse the repository at this point in the history
If the same model was set in the configuration
and the container, the init would produce a new
model, even though that wasn't necessary.
This would then produce the "model type" claimed
by multiple entity descriptions issue.
  • Loading branch information
helje5 committed Jun 27, 2024
1 parent e96080b commit 97921f6
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
20 changes: 17 additions & 3 deletions Sources/ManagedModels/Container/NSPersistentContainer+Data.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2023 ZeeZide GmbH.
// Copyright © 2023-2024 ZeeZide GmbH.
//

import CoreData
Expand All @@ -27,9 +27,21 @@ extension NSPersistentContainer {
precondition(migrationPlan == nil, "Migration plans not yet supported")

let combinedModel : NSManagedObjectModel = {
let allModels = [ model ] + configurations.compactMap { $0.schema }
guard let firstConfig = configurations.first else { return model }
if configurations.count == 1,
firstConfig.schema == nil || firstConfig.schema == model
{
return model
}

var allModels = [ ObjectIdentifier : NSManagedObjectModel ]()
allModels[ObjectIdentifier(model)] = model
for config in configurations {
guard let model = config.schema else { continue }
allModels[ObjectIdentifier(model)] = model
}
guard allModels.count > 1 else { return model }
let merged = NSManagedObjectModel(byMerging: allModels)
let merged = NSManagedObjectModel(byMerging: Array(allModels.values))
assert(merged != nil, "Could not combine object models: \(allModels)")
return merged ?? model
}()
Expand Down Expand Up @@ -84,6 +96,7 @@ extension NSPersistentContainer {

public extension NSPersistentContainer {

@inlinable
convenience init(for model : NSManagedObjectModel,
migrationPlan : SchemaMigrationPlan.Type? = nil,
configurations : ModelConfiguration...) throws
Expand All @@ -92,6 +105,7 @@ public extension NSPersistentContainer {
configurations: configurations)
}

@inlinable
convenience init(for types : any PersistentModel.Type...,
migrationPlan : SchemaMigrationPlan.Type? = nil,
configurations : ModelConfiguration...) throws
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2023 ZeeZide GmbH.
// Copyright © 2023-2024 ZeeZide GmbH.
//

import CoreData
Expand Down Expand Up @@ -36,7 +36,7 @@ public extension NSManagedObjectModel {

// MARK: - Cached ManagedObjectModels

private let lock = NSLock()
private let lock = NSLock() // TODO: Use new UnfairLock if available
#if swift(>=5.10)
nonisolated(unsafe)
private var map = [ Set<ObjectIdentifier> : NSManagedObjectModel ]()
Expand All @@ -48,14 +48,31 @@ nonisolated private let sharedBuilder = SchemaBuilder()

public extension NSManagedObjectModel {

/// A cached version of the initializer.
static func model(for versionedSchema: VersionedSchema.Type)
/**
* This caches a model for the types in the given `VersionedSchema`.
* I.e. it will return the same `NSManagedObjectModel` when given the same
* types.
*
* - Parameters:
* - versionedSchema: The versioned schema to derive the model from.
* - Returns: A `NSManagedObjectModel` representing the schema.
*/
@inlinable
static func model(for versionedSchema: VersionedSchema.Type)
-> NSManagedObjectModel
{
model(for: versionedSchema.models)
}

/// A cached version of the initializer.
/**
* This caches a model for the types passed in.
* I.e. it will return the same `NSManagedObjectModel` when given the same
* types.
*
* - Parameters:
* - types: A set of `PersistentModel` types, e.g. `[Person.self]`.
* - Returns: A `NSManagedObjectModel` representing the types.
*/
static func model(for types: [ any PersistentModel.Type ])
-> NSManagedObjectModel
{
Expand Down

0 comments on commit 97921f6

Please sign in to comment.