Skip to content

Commit 97921f6

Browse files
committed
Fix a bug in model merging
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.
1 parent e96080b commit 97921f6

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

Sources/ManagedModels/Container/NSPersistentContainer+Data.swift

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//
22
// Created by Helge Heß.
3-
// Copyright © 2023 ZeeZide GmbH.
3+
// Copyright © 2023-2024 ZeeZide GmbH.
44
//
55

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

2929
let combinedModel : NSManagedObjectModel = {
30-
let allModels = [ model ] + configurations.compactMap { $0.schema }
30+
guard let firstConfig = configurations.first else { return model }
31+
if configurations.count == 1,
32+
firstConfig.schema == nil || firstConfig.schema == model
33+
{
34+
return model
35+
}
36+
37+
var allModels = [ ObjectIdentifier : NSManagedObjectModel ]()
38+
allModels[ObjectIdentifier(model)] = model
39+
for config in configurations {
40+
guard let model = config.schema else { continue }
41+
allModels[ObjectIdentifier(model)] = model
42+
}
3143
guard allModels.count > 1 else { return model }
32-
let merged = NSManagedObjectModel(byMerging: allModels)
44+
let merged = NSManagedObjectModel(byMerging: Array(allModels.values))
3345
assert(merged != nil, "Could not combine object models: \(allModels)")
3446
return merged ?? model
3547
}()
@@ -84,6 +96,7 @@ extension NSPersistentContainer {
8496

8597
public extension NSPersistentContainer {
8698

99+
@inlinable
87100
convenience init(for model : NSManagedObjectModel,
88101
migrationPlan : SchemaMigrationPlan.Type? = nil,
89102
configurations : ModelConfiguration...) throws
@@ -92,6 +105,7 @@ public extension NSPersistentContainer {
92105
configurations: configurations)
93106
}
94107

108+
@inlinable
95109
convenience init(for types : any PersistentModel.Type...,
96110
migrationPlan : SchemaMigrationPlan.Type? = nil,
97111
configurations : ModelConfiguration...) throws

Sources/ManagedModels/SchemaCompatibility/NSManagedObjectModel+Data.swift

+22-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//
22
// Created by Helge Heß.
3-
// Copyright © 2023 ZeeZide GmbH.
3+
// Copyright © 2023-2024 ZeeZide GmbH.
44
//
55

66
import CoreData
@@ -36,7 +36,7 @@ public extension NSManagedObjectModel {
3636

3737
// MARK: - Cached ManagedObjectModels
3838

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

4949
public extension NSManagedObjectModel {
5050

51-
/// A cached version of the initializer.
52-
static func model(for versionedSchema: VersionedSchema.Type)
51+
/**
52+
* This caches a model for the types in the given `VersionedSchema`.
53+
* I.e. it will return the same `NSManagedObjectModel` when given the same
54+
* types.
55+
*
56+
* - Parameters:
57+
* - versionedSchema: The versioned schema to derive the model from.
58+
* - Returns: A `NSManagedObjectModel` representing the schema.
59+
*/
60+
@inlinable
61+
static func model(for versionedSchema: VersionedSchema.Type)
5362
-> NSManagedObjectModel
5463
{
5564
model(for: versionedSchema.models)
5665
}
5766

58-
/// A cached version of the initializer.
67+
/**
68+
* This caches a model for the types passed in.
69+
* I.e. it will return the same `NSManagedObjectModel` when given the same
70+
* types.
71+
*
72+
* - Parameters:
73+
* - types: A set of `PersistentModel` types, e.g. `[Person.self]`.
74+
* - Returns: A `NSManagedObjectModel` representing the types.
75+
*/
5976
static func model(for types: [ any PersistentModel.Type ])
6077
-> NSManagedObjectModel
6178
{

0 commit comments

Comments
 (0)