Considerations for schema migration

To evolve your @Model schema across app versions, use SwiftData's standard migration mechanisms (VersionedSchema, SchemaMigrationPlan, MigrationStage, and @Attribute(originalName:)). Define your versioned schemas and plan as usual, then pass the plan to GDSecureModelContainer.create(_:migrationPlan:).

let config = try GDSecureModelConfiguration(name: "Notes",
                                            versionedSchema: NotesSchemaV2.self,
                                            storeURL: storeURL)
let container = try GDSecureModelContainer.create(config,
                                                  migrationPlan: NotesMigrationPlan.self)

Before you ship a schema change, review the following considerations for the BlackBerry Dynamics secure store.

Consideration

Details

Migration plans require VersionedSchema

A migrationPlan: argument works only with a configuration built from the versionedSchema: initializer of GDSecureModelConfiguration. If you pass a plan to a configuration built from bare models:, create(...) throws migrationFailed. A bare-models: configuration supports lightweight migration only (the no-plan call, which infers simple changes automatically). When you need a plan, move to VersionedSchema.

Widen required to optional (String to String?)

Automatic lightweight migration is supported. You can ship the change without a custom migration stage.

Drop a relationship

Automatic lightweight migration is supported. There is no automatic orphan cleanup. If you need cascade-delete behavior, implement it in a .custom stage.

Rename a property with @Attribute(originalName:)

Automatic lightweight migration is supported when you include the @Attribute(originalName: "oldName") hint. Always include the hint when you rename a property.

Change an attribute's type

Automatic migration is not supported for type changes such as String to Int or String to URL. Use a .custom stage: read the old value in willMigrate and write the converted value in didMigrate.

Tighten optional to required when null values exist

Automatic migration is not supported. Backfill null values in a .custom willMigrate first, or give the property a default.

Add a new required field with no default

Automatic migration is not supported. Make the field optional, give it a default, or populate it in a .custom didMigrate.

Rename a property without @Attribute(originalName:)

Automatic migration is not supported. The migration fails instead of silently discarding data. Add the @Attribute(originalName:) hint.

Migration failure

When a migration fails, the BlackBerry Dynamics SDK throws an error with code migrationFailed. Migration runs entirely inside create(...), so you handle the failure at container-creation time. For related symptoms and solutions, see Troubleshooting SwiftData integration.