I am trying to convert a string field to an integer field in our database schema. However, the custom migration that I write doesn't seem to run.
My Model
//Run 1
//typealias Book = BookSchemaV1.Book
//Run 2
typealias Book = BookSchemaV2.Book
// MARK: - Migration Plan
enum BookModelMigrationPlan: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] = [
BookSchemaV1.self,
BookSchemaV2.self
]
static var stages: [MigrationStage] = [migrateV1toV2]
static var oldBooks: [BookSchemaV1.Book] = []
static let migrateV1toV2 = MigrationStage.custom(
fromVersion: BookSchemaV1.self,
toVersion: BookSchemaV2.self,
willMigrate: nil,
didMigrate: { context in
oldBooks = try context.fetch(FetchDescriptor<BookSchemaV1.Book>())
oldBooks.forEach { oldBook in
do {
let newBook = BookSchemaV2.Book(
bookID: String(oldBook.bookID),
title: oldBook.title
)
context.insert(newBook)
context.delete(oldBook)
try context.save()
} catch {
print("New model not saved")
}
}
}
)
}
// MARK: - Schema Versions
enum BookSchemaV1: VersionedSchema {
static var models: [any PersistentModel.Type] = [Book.self]
static var versionIdentifier = Schema.Version(1, 0, 0)
@Model
final class Book {
@Attribute(.unique) var bookID: Int
var title: String
init(
bookID: Int,
title: String
) {
self.bookID = bookID
self.title = title
}
}
}
enum BookSchemaV2: VersionedSchema {
static var models: [any PersistentModel.Type] = [Book.self]
static var versionIdentifier = Schema.Version(2, 0, 0)
@Model
class Book {
@Attribute(.unique) var bookID: String
var title: String
init(
bookID: String,
title: String
) {
self.bookID = bookID
self.title = title
}
}
}
@MainActor
class AppDataContainer {
static let shared = AppDataContainer()
let container: ModelContainer
private init() {
do {
let schema = Schema([Book.self])
let config = ModelConfiguration(schema: schema)
container = try ModelContainer(for: schema, migrationPlan: BookModelMigrationPlan.self, configurations: [config])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}
}