If you're just renaming a property, you shouldn't need an explicit migration plan and could instead rely on automatic migration, using the originalName
parameter of the @Attribute
macro:
@Attribute(originalName: "name") let title: String
In terms of how the willMigrate and didMigrate closures work when you do write a custom migration stage, the SwiftData documentation currently isn't helpful, but the equivalent Core Data documentation offers some insight:
The handlers provide an opportunity to prepare the persistent store’s data for the upcoming changes before the stage runs, and perform any cleanup tasks afterward.
For example, to support a migration that changes an optional attribute to be nonoptional, you might assign a handler to the stage’s willMigrateHandler property that sets any nil instances of that attribute to a default value, thereby ensuring the migration succeeds.
The way I understand it is that at its core, a custom stage actually does the same as a lightweight stage, but the two handlers allow you to prepare the data so that the automatic part of the stage can succeed, and to do some clean-up afterwards if you need to.
I guess if you did want to rename a field using a custom stage, you'd have to:
- Add an optional
title
attribute in the V1 model alongside the original name
attribute, to allow you to copy the value over.* - In the willMigrate closure, get all the V1 objects and copy their
name
value into their title
field. - The automatic part of the migration stage can now run safely, making
title
non-optional and removing the name
field.
* Note that if your original model wasn't part of an explicit VersionedSchema, you can't introduce the title
field in your now-explicit V1 schema because SwiftData won't recognise it as being the same as the implicit 1.0.0 schema it had created. To get around this, I had to create an intermediate schema (1.1.0) with the new field, and added a lightweight migration stage (from 1.0.0 to 1.1.0) to introduce the field before the custom stage (from 1.1.0 to 2.0.0) populated it.