Skip to content

Commit c5e5567

Browse files
committed
Merge branch 'develop'
2 parents 885e546 + c910edf commit c5e5567

10 files changed

+89
-44
lines changed

Package.swift

+12-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
import PackageDescription
33
import CompilerPluginSupport
44

5+
#if swift(>=5.10)
6+
let settings = [ .enableExperimentalFeature("StrictConcurrency") ]
7+
#else
8+
let settings = [ SwiftSetting ]()
9+
#endif
10+
511
let package = Package(
612
name: "ManagedModels",
713

@@ -13,8 +19,12 @@ let package = Package(
1319
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0")
1420
],
1521
targets: [
16-
.target(name: "ManagedModels", dependencies: [ "ManagedModelMacros" ]),
17-
22+
.target(
23+
name: "ManagedModels",
24+
dependencies: [ "ManagedModelMacros" ],
25+
swiftSettings: settings
26+
),
27+
1828
.macro(
1929
name: "ManagedModelMacros",
2030
dependencies: [

Sources/ManagedModels/Container/ModelConfiguration.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
// Copyright © 2023 ZeeZide GmbH.
44
//
55

6-
import CoreData
6+
@preconcurrency import CoreData
77

8-
public struct ModelConfiguration: Hashable {
8+
public struct ModelConfiguration: Hashable, Sendable {
99
// TBD: Some of those are `let` in SwiftData
1010

1111
public var path : String
@@ -83,7 +83,7 @@ extension ModelConfiguration: Identifiable {
8383

8484
public extension ModelConfiguration {
8585

86-
struct GroupContainer: Hashable {
86+
struct GroupContainer: Hashable, Sendable {
8787
enum Value: Hashable {
8888
case automatic, none
8989
case identifier(String)
@@ -100,7 +100,7 @@ public extension ModelConfiguration {
100100

101101
public extension ModelConfiguration {
102102

103-
struct CloudKitDatabase: Hashable {
103+
struct CloudKitDatabase: Hashable, Sendable {
104104
enum Value: Hashable {
105105
case automatic, none
106106
case `private`(String)

Sources/ManagedModels/PersistentModel/PropertyMetadata.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public extension NSManagedObjectModel {
1313
* All (code defined) properties of the ``NSManagedObjectModel`` are stored
1414
* in the `schemaMetadata` static property.
1515
*/
16-
struct PropertyMetadata {
16+
struct PropertyMetadata: @unchecked Sendable {
1717

1818
/// The name of the property instance variable, e.g. `street`.
1919
public let name : String

Sources/ManagedModels/Schema/AttributeOption.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import class Foundation.ValueTransformer
77

88
extension NSAttributeDescription {
99

10-
public struct Option: Equatable {
10+
public struct Option: Equatable, Sendable {
1111

1212
let value : Value
1313

@@ -39,7 +39,7 @@ extension NSAttributeDescription {
3939

4040
extension NSAttributeDescription.Option {
4141

42-
enum Value {
42+
enum Value: Sendable {
4343
case unique, externalStorage, preserveValueOnDeletion, ephemeral, spotlight
4444
case transformableByType(ValueTransformer.Type)
4545
case transformableByName(String)

Sources/ManagedModels/Schema/RelationshipOption.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import CoreData
77

88
public extension NSRelationshipDescription {
99

10-
struct Option: Equatable {
10+
struct Option: Equatable, Sendable {
1111

12-
enum Value {
12+
enum Value: Sendable {
1313
case unique
1414
}
1515
let value : Value

Sources/ManagedModels/SchemaCompatibility/CoreDataPrimitiveValue.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import CoreData
77

88
public extension CoreData.NSAttributeDescription {
9-
struct TypeConfiguration {
9+
struct TypeConfiguration: Sendable {
1010
let attributeType : NSAttributeType
1111
let isOptional : Bool
1212
let attributeValueClassName : String?

Sources/ManagedModels/SchemaCompatibility/NSManagedObjectModel+Data.swift

+7-1
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,14 @@ public extension NSManagedObjectModel {
3737
// MARK: - Cached ManagedObjectModels
3838

3939
private let lock = NSLock()
40+
#if swift(>=5.10)
41+
nonisolated(unsafe)
4042
private var map = [ Set<ObjectIdentifier> : NSManagedObjectModel ]()
41-
private let sharedBuilder = SchemaBuilder()
43+
nonisolated(unsafe) private let sharedBuilder = SchemaBuilder()
44+
#else // 5.9: nonisolated(unsafe) not available, nonisolated nor working on var
45+
private var map = [ Set<ObjectIdentifier> : NSManagedObjectModel ]()
46+
nonisolated private let sharedBuilder = SchemaBuilder()
47+
#endif
4248

4349
public extension NSManagedObjectModel {
4450

Sources/ManagedModels/SchemaCompatibility/NSPropertyDescription+Data.swift

+26-11
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,44 @@
33
// Copyright © 2023 ZeeZide GmbH.
44
//
55

6-
private var _propertyIsUniqueAssociatedKey: UInt8 = 42
7-
86
extension NSPropertyDescription {
9-
7+
private struct AssociatedKeys {
8+
#if swift(>=5.10)
9+
nonisolated(unsafe) static var propertyIsUniqueAssociatedKey: Void? = nil
10+
#else // 5.9: nonisolated(unsafe) not available
11+
static var propertyIsUniqueAssociatedKey: Void? = nil
12+
#endif
13+
}
14+
1015
public internal(set) var isUnique: Bool {
1116
// Note: isUnique is only used during schema construction!
1217
set {
1318
if newValue {
14-
objc_setAssociatedObject(self, &_propertyIsUniqueAssociatedKey,
15-
type(of: self), .OBJC_ASSOCIATION_ASSIGN)
19+
objc_setAssociatedObject(
20+
self, &AssociatedKeys.propertyIsUniqueAssociatedKey,
21+
type(of: self), // Just used as a flag, type won't go away
22+
.OBJC_ASSOCIATION_ASSIGN
23+
)
1624
}
1725
else {
18-
objc_setAssociatedObject(self, &_propertyIsUniqueAssociatedKey, nil, .OBJC_ASSOCIATION_RETAIN)
26+
objc_setAssociatedObject(
27+
self, &AssociatedKeys.propertyIsUniqueAssociatedKey,
28+
nil, // clear // clear flag
29+
.OBJC_ASSOCIATION_ASSIGN
30+
)
1931
}
20-
#if false // do we need this? The entity might not yet be setup?
32+
#if false // do we need this? The entity might not yet be setup?
2133
guard !entity.isPropertyUnique(self) else { return }
2234
entity.uniquenessConstraints.append( [ self ])
23-
#endif
35+
#endif
2436
}
2537
get {
26-
objc_getAssociatedObject(self, &_propertyIsUniqueAssociatedKey) != nil
27-
? true
28-
: entity.isPropertyUnique(self)
38+
objc_getAssociatedObject(
39+
self,
40+
&AssociatedKeys.propertyIsUniqueAssociatedKey
41+
) != nil
42+
? true
43+
: entity.isPropertyUnique(self)
2944
}
3045
}
3146
}

Sources/ManagedModels/SchemaCompatibility/NSRelationshipDescription+Data.swift

+28-20
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ extension CoreData.NSRelationshipDescription {
1313
extension CoreData.NSRelationshipDescription: SchemaProperty {}
1414

1515
public extension CoreData.NSRelationshipDescription {
16-
16+
1717
@inlinable var isToOneRelationship : Bool { !isToMany }
18-
18+
1919
@inlinable var isAttribute : Bool { return false }
2020
@inlinable var isRelationship : Bool { return true }
2121

@@ -109,7 +109,7 @@ extension CoreData.NSRelationshipDescription {
109109
// MARK: - Initializer
110110

111111
public extension CoreData.NSRelationshipDescription {
112-
112+
113113
// Note: This matches what the `Relationship` macro takes.
114114
convenience init(_ options: Option..., deleteRule: NSDeleteRule = .nullify,
115115
minimumModelCount: Int? = 0, maximumModelCount: Int? = 0,
@@ -122,16 +122,16 @@ public extension CoreData.NSRelationshipDescription {
122122
precondition(minimumModelCount ?? 0 >= 0)
123123
precondition(maximumModelCount ?? 0 >= 0)
124124
self.init()
125-
125+
126126
self.name = name ?? ""
127127
self.valueType = valueType
128128
self.renamingIdentifier = originalName ?? ""
129129
self.versionHashModifier = hashModifier
130130
self.deleteRule = deleteRule
131131
self.inverseKeyPath = inverse
132-
132+
133133
if options.contains(.unique) { isUnique = true }
134-
134+
135135
if let minimumModelCount { self.minCount = minimumModelCount }
136136
if let maximumModelCount {
137137
self.maxCount = maximumModelCount
@@ -140,7 +140,7 @@ public extension CoreData.NSRelationshipDescription {
140140
if valueType is any RelationshipCollection.Type {
141141
self.maxCount = 0
142142
}
143-
else if valueType is NSOrderedSet.Type ||
143+
else if valueType is NSOrderedSet.Type ||
144144
valueType is Optional<NSOrderedSet>.Type
145145
{
146146
self.maxCount = 0
@@ -155,10 +155,8 @@ public extension CoreData.NSRelationshipDescription {
155155

156156
// MARK: - Storage
157157

158-
private var _relationshipInfoAssociatedKey: UInt8 = 72
159-
160158
extension CoreData.NSRelationshipDescription {
161-
159+
162160
func internalCopy() -> Self {
163161
guard let copy = self.copy() as? Self else {
164162
fatalError("Could not copy relationship \(self)")
@@ -187,7 +185,7 @@ extension CoreData.NSRelationshipDescription {
187185
var inverseName : String?
188186
var destination : String?
189187
var isToOneRelationship : Bool?
190-
188+
191189
override func copy() -> Any { internalCopy() }
192190

193191
func internalCopy() -> MacroInfo {
@@ -201,11 +199,18 @@ extension CoreData.NSRelationshipDescription {
201199
return copy
202200
}
203201
}
204-
202+
203+
private struct AssociatedKeys {
204+
#if swift(>=5.10)
205+
nonisolated(unsafe) static var relationshipInfoAssociatedKey: Void? = nil
206+
#else // 5.9: nonisolated(unsafe) not available
207+
static var relationshipInfoAssociatedKey: Void? = nil
208+
#endif
209+
}
210+
205211
var writableRelationshipInfo : MacroInfo {
206-
if let info =
207-
objc_getAssociatedObject(self, &_relationshipInfoAssociatedKey)
208-
as? MacroInfo
212+
if let info = objc_getAssociatedObject(
213+
self, &AssociatedKeys.relationshipInfoAssociatedKey) as? MacroInfo
209214
{
210215
return info
211216
}
@@ -214,16 +219,19 @@ extension CoreData.NSRelationshipDescription {
214219
self.relationshipInfo = info
215220
return info
216221
}
217-
222+
218223
var relationshipInfo: MacroInfo? {
219224
// Note: isUnique is only used during schema construction!
220225
set {
221-
objc_setAssociatedObject(self, &_relationshipInfoAssociatedKey,
222-
newValue, .OBJC_ASSOCIATION_RETAIN)
226+
objc_setAssociatedObject(
227+
self, &AssociatedKeys.relationshipInfoAssociatedKey,
228+
newValue, .OBJC_ASSOCIATION_RETAIN
229+
)
223230
}
224231
get {
225-
objc_getAssociatedObject(self, &_relationshipInfoAssociatedKey)
226-
as? MacroInfo
232+
objc_getAssociatedObject(
233+
self, &AssociatedKeys.relationshipInfoAssociatedKey
234+
) as? MacroInfo
227235
}
228236
}
229237
}

Sources/ManagedModels/SwiftUI/ModelContainer+SwiftUI.swift

+6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public extension View {
2525
self.modelContext(container.viewContext)
2626
}
2727

28+
@MainActor
2829
@ViewBuilder
2930
func modelContainer(
3031
for modelTypes : [ any PersistentModel.Type ],
@@ -48,6 +49,7 @@ public extension View {
4849
}
4950
}
5051

52+
@MainActor
5153
@inlinable
5254
func modelContainer(
5355
for modelType : any PersistentModel.Type,
@@ -73,6 +75,7 @@ public extension Scene {
7375
self.modelContext(container.viewContext)
7476
}
7577

78+
@MainActor
7679
@SceneBuilder
7780
func modelContainer(
7881
for modelTypes : [ any PersistentModel.Type ],
@@ -92,6 +95,7 @@ public extension Scene {
9295
self.modelContainer(try! result.get())
9396
}
9497

98+
@MainActor
9599
@inlinable
96100
func modelContainer(
97101
for modelType : any PersistentModel.Type,
@@ -113,8 +117,10 @@ public extension Scene {
113117
// MARK: - Primitive
114118

115119
// Note: The docs say that a container is only ever created once! So cache it.
120+
@MainActor
116121
private var modelToContainer = [ ObjectIdentifier: NSPersistentContainer ]()
117122

123+
@MainActor
118124
private func makeModelContainer(
119125
for modelTypes : [ any PersistentModel.Type ],
120126
inMemory : Bool = false,

0 commit comments

Comments
 (0)