SwiftData Schema Migration Plan when the type of a field in your model changes

Hi I am trying to figure out how to properly migrate my schema when a field in my model needs to become a different type.

I start with a simple model User with an array of type String called friends

    @Model
    final class User {
        @Attribute(.unique) var id: String
        var friends: [String]?
    }

Now I want to change the type of friends to [User]? but I am unsure how to make a migration plan for this. I created two versioned schemas

enum UserSchemaV1: VersionedSchema {
    static var versionIdentifier = Schema.Version(1, 0, 0)
    
    static var models: [any PersistentModel.Type] {
            [User.self]
        }
    
    @Model
    final class User {
        @Attribute(.unique) var id: String
        var friends: [String]?
    }
}
enum UserSchemaV2: VersionedSchema {
    static var versionIdentifier = Schema.Version(2, 0, 0)
    
    static var models: [any PersistentModel.Type] {
            [User.self]
        }
    
    @Model
    final class User {
        @Attribute(.unique) var id: String
        var friends: [User]?
    }
}

Then I make a migration plan

enum UsersMigrationPlan: SchemaMigrationPlan {
    static var stages: [MigrationStage] {
        [migrateV1toV2]
    }
    
    static var schemas: [any VersionedSchema.Type] {
        [UserSchemaV1.self, UserSchemaV2.self]
    }
    
    static let migrateV1toV2 = MigrationStage.custom(
        fromVersion: UserSchemaV1.self,
        toVersion: UserSchemaV2.self,
        willMigrate: nil,
        didMigrate: nil
    )
}

And I make a container using my migration plan

    let container: ModelContainer
    
    init() {
        do {
            container = try ModelContainer(for: User.self,
                                           migrationPlan: UsersMigrationPlan.self
            )
        } catch {
            fatalError("Failed to initialize user model container")
        }
    }

I also use a typealias so I can keep using User in my code typealias User = UserSchemaV2.User

But no matter what I try I get an error when running my code Thread 1: Fatal error: Unknown related type - User

In the closure for v2 of the Schema

    set {
                    _$observationRegistrar.withMutation(of: self, keyPath: \.friends) {
                            self.setValue(forKey: \.friends, to: newValue)
                    }
        }

What am I misunderstanding about migrating my schema with this change? Is this something that's possible when doing a schema migration? Is there a simple/better/easier way to modify my schema to change the type of the field?

You have to write some code that does the migration in the custom migration stage's willMigrate / didMigrate. There is a sample here: https://www.hackingwithswift.com/quick-start/swiftdata/how-to-store-swiftdata-attributes-in-an-external-file - although I'm not finding any more detailed resources on how to migrate and when to use will- or did-Migrate, so I guess we'll just have to try it out.

SwiftData Schema Migration Plan when the type of a field in your model changes
 
 
Q