I'm very new to SwiftData and have run into an issue where I need to change a datatype in a model. I've attempted to implement a migration plan but my original schema was not of type VersionedSchema so I keep getting the following error.
Unresolved error loading container Error Domain=NSCocoaErrorDomain Code=134504 "Cannot use staged migration with an unknown model version." UserInfo={NSLocalizedDescription=Cannot use staged migration with an unknown model version.}.
This is already a released app so I'm trying not to nuke data. Can someone please guide me in the right direction to fix this?
@main
struct AuditApp: App {
var sharedModelContainer: ModelContainer = {
let modelConfiguration = ModelConfiguration(schema: Schema(SchemaV2.models).self, isStoredInMemoryOnly: false)
do {
return try ModelContainer(for: Schema(SchemaV2.models), migrationPlan: AuditMigrationPlan.self, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
var body: some Scene {
WindowGroup {
RootView()
.preferredColorScheme(.light) // Force light mode
}
.modelContainer(sharedModelContainer)
}
}
import Foundation
import SwiftData
enum SchemaV1: VersionedSchema {
static var models: [any PersistentModel.Type] {
[
WaterSpraySystemAudit.self,
CannonServiceInspectionReport.self,
StripAndAssessReport.self,
FileType.self,
AppSettings.self
]
}
static var versionIdentifier: Schema.Version = Schema.Version(1, 0, 0)
}
enum SchemaV1_1: VersionedSchema {
static var models: [any PersistentModel.Type] {
[
WaterSpraySystemAudit.self,
CannonServiceInspectionReportV1_1.self,
StripAndAssessReport.self,
FileType.self,
AppSettings.self
]
}
static var versionIdentifier: Schema.Version = Schema.Version(1, 1, 0)
}
enum SchemaV2: VersionedSchema {
static var models: [any PersistentModel.Type] {
[
WaterSpraySystemAudit.self,
CannonServiceInspectionReportV2.self,
StripAndAssessReport.self,
FileType.self,
AppSettings.self
]
}
static var versionIdentifier: Schema.Version = Schema.Version(2, 0, 0)
}
enum AuditMigrationPlan: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] {
[SchemaV1.self, SchemaV1_1.self, SchemaV2.self]
}
static var stages: [MigrationStage] {
[
migrateV1toV1_1,
migrateV1_1toV2
]
}
static let migrateV1toV1_1: MigrationStage = .custom(
fromVersion: SchemaV1.self,
toVersion: SchemaV1_1.self,
willMigrate: nil,
didMigrate: { context in
let reports = try context.fetch(FetchDescriptor<CannonServiceInspectionReportV1_1>())
for report in reports {
report.ListOfPartsString = report.ListOfParts?.joined(separator: "\n")
}
try context.save()
}
)
static let migrateV1_1toV2: MigrationStage = .lightweight(
fromVersion: SchemaV1_1.self,
toVersion: SchemaV2.self
)
}
For reference this was the orignal non versioned setup
@main
struct AuditApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([
WaterSpraySystemAudit.self,
CannonServiceInspectionReport.self,
StripAndAssessReport.self,
FileType.self,
AppSettings.self
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
var body: some Scene {
WindowGroup {
RootView()
.preferredColorScheme(.light) // Force light mode
}
.modelContainer(sharedModelContainer)
}
}