I use SwiftData in my app and I want to update a property in my model.
This property (lets call it myData) is a Codable struct.
I have added to new properties in myData, without changing anything in my model, it crashes at app start.
If I erase the app and start from scratch, it works perfectly with my updated model.
I think there is a problem with schema migration but I don’t know how to handle it.
I use SwiftData in my app and I want to update a property in my model.
This property (lets call it myData) is a Codable struct.
I have added to new properties in myData, without changing anything in my model, it crashes at app start.
If I erase the app and start from scratch, it works perfectly with my updated model.
I think there is a problem with schema migration but I don’t know how to handle it.
Some more info, my model:
@Model
class CloudInterval: Encodable, Comparable {
var id = UUID()
var name: String = ""
var order: Int = 0
// targets
var targetData = TargetData()
@Relationship(deleteRule: .nullify, inverse: CloudBlock.intervals)
var block: CloudBlock?
init() {
}
}
My problem is with targetData
Initially, it’s :
struct TargetData: Codable, Equatable {
var minHeartRate: Int = 0
var maxHeartRate: Int = 0
var speed: Double = 0
var time: TimeInterval = 0
var distance: Double = 0
var enableTargetSpeed = false
var enableTargetHeartRate = false
var enableTargetTime = false
var speedTolerance: Double = 0.02
}
And I just want to add 2 new properties (1 Bool, 1 Int), and when I do that, the app crashes.
I don’t how to migrate to the new version.
2
Answers
There is 2 type of migrations in SwiftData: lightweight and complex.
While lightweight migration will execute automatically, for bigger changes you need to write your own migration plan.
Some lightweight changess:
The problem in you case is you want to update a complex type, not only add two more properties.
You have more options to solve this:
1. You can make the TargetData
@Model
as well, and create one-to-one relationships between them.This mean that every
CloudInterval
object has exactly oneTargetData
object attached to it.In this case, be careful not to try to insert both
CloudInterval
andTargetData
objects, because inserting one automatically inserts the other.2. You can create complex migration using
VersionedSchema
Doing this requires four steps:
You can learn more about
SchemaMigrationPlan
from the following links:WWDC Notes
HackingWithSwift
You should make migrations when you want to make changes to your data model. If your app is not published on the App Store, I recommend deleting your application and reinstalling it. However, if you want to update your app that is on the App Store, I prefer watching this video. SwiftData Migrations Tutorial