I bought two fashions right here:
@Mannequin
last class PresetParams: Identifiable {
@Attribute(.distinctive) var id: UUID = UUID()
var positionX: Float = 0.0
var positionY: Float = 0.0
var positionZ: Float = 0.0
var quantity: Float = 1.0
@Relationship(deleteRule: .nullify, inverse: Preset.presetAudioParams)
var preset = [Preset]()
init(place: SIMD3, quantity: Float) {
self.positionX = place.x
self.positionY = place.y
self.positionZ = place.z
self.quantity = quantity
self.preset = []
}
var place: SIMD3 {
get {
return SIMD3(x: positionX, y: positionY, z: positionZ)
}
set {
positionX = newValue.x
positionY = newValue.y
positionZ = newValue.z
}
}
}
@Mannequin
last class Preset: Identifiable {
@Attribute(.distinctive) var id: UUID = UUID()
var presetName: String
var presetDesc: String?
var presetAudioParams = [PresetParams]() // Many-To-Many Relationship.
init(presetName: String, presetDesc: String? = nil) {
self.presetName = presetName
self.presetDesc = presetDesc
self.presetAudioParams = []
}
}
To be trustworthy, I do not absolutely perceive how the @Relationship
factor works correctly in a Many-To-Many relationship state of affairs. Some tutorials recommend that it is required on the “One” facet of an One-To-Many Relationship, whereas the “Many” facet does not want it.
After which there’s an ObservableObject known as “ModelActors” to handle all ModelActors, ModelContainer, and so forth.
class ModelActors: ObservableObject {
static let shared: ModelActors = ModelActors()
let sharedModelContainer: ModelContainer
personal init() {
var schema = Schema([
// ...
Preset.self,
PresetParams.self,
// ...
])
do {
sharedModelContainer = attempt ModelContainer(for: schema, migrationPlan: MigrationPlan.self)
} catch {
fatalError("Couldn't create ModelContainer: (error.localizedDescription)")
}
}
}
And there’s a migrationPlan:
// MARK: V102
// typealias ...
// MARK: V101
typealias Preset = AppSchemaV101.Preset
typealias PresetParams = AppSchemaV101.PresetParams
// MARK: V100
// typealias ...
enum MigrationPlan: SchemaMigrationPlan {
static var schemas: [VersionedSchema.Type] {
[
AppSchemaV100.self,
AppSchemaV101.self,
AppSchemaV102.self,
]
}
static var phases: [MigrationStage] {
[AppMigrateV100toV101, AppMigrateV101toV102]
}
static let AppMigrateV100toV101 = MigrationStage.light-weight(fromVersion: AppSchemaV100.self, toVersion: AppSchemaV101.self)
static let AppMigrateV101toV102 = MigrationStage.light-weight(fromVersion: AppSchemaV101.self, toVersion: AppSchemaV102.self)
}
// MARK: Right here is the AppSchemaV101
enum AppSchemaV101: VersionedSchema {
static var versionIdentifier: Schema.Model = Schema.Model(1, 0, 1)
static var fashions: [any PersistentModel.Type] {
return [ // ...
Preset.self,
PresetParams.self
]
}
}
So I anticipated the SwiftData subsystem to work appropriately with model management. A excellent news is that on `iOS 18.1 `it does work. But it surely fails on iOS 18.3.x
with a deadly Error:
"SwiftData/SchemaCoreData.swift:581: Deadly error: Failed to satisfy hyperlink PendingRelationshipLink(relationshipDescription: (), identify preset, isOptional 0, isTransient 0, entity PresetParams, renamingIdentifier preset, validation predicates (), warnings (), versionHashModifier (null)userInfo {}, vacation spot entity Preset, inverseRelationship (null), minCount 0, maxCount 0, isOrdered 0, deleteRule 1, destinationEntityName: "Preset", inverseRelationshipName: Elective("presetAudioParams")), could not discover inverse relationship 'Preset.presetAudioParams' in mannequin"
I examined it on iOS 17.5
and located one other subject: Accessing or mutating the "PresetAudioParams"
property causes the SwiftData Macro Codes to crash, affecting each Getter
and Setter
. It fails with an error "EXC_BREAKPOINT (code=1, subcode=0x1cc1698ec)"
Tweaking the @Relationship marker and ModelContainer settings did not repair the issue.