I'm trying to test migration between schemas but I cannot get it to work properly. I've never been able to get a complex migration to work properly unfortunately. I've removed a property and added 2 new ones to one of my data models.
This is my current plan.
enum MigrationV1toV2: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] {
[SchemaV1.self, SchemaV2.self]
}
static let migrateV1toV2 = MigrationStage.custom(
fromVersion: SchemaV1.self,
toVersion: SchemaV2.self,
willMigrate: { context in
print("Inside will migrate")
// Get old months
let oldMonths = try context.fetch(FetchDescriptor<SchemaV1.Month>())
print("Number of old months:\(oldMonths.count)")
for oldMonth in oldMonths {
// Convert to new month
let newMonth = Month(name: oldMonth.name, year: oldMonth.year, limit: oldMonth.limit)
print("Number of transactions in oldMonth: \(oldMonth.transactions?.count)")
print("Number of transactions in newMonth: \(newMonth.transactions?.count)")
// Convert transactions
for transaction in oldMonth.transactions ?? [] {
// Set action and direction
let action = getAction(from: transaction)
let direction = getDirection(from: transaction)
// Update category if necessary
var category: TransactionCategory? = nil
if let oldCategory = transaction.category {
category = TransactionCategory(
name: oldCategory.name,
color: SchemaV2.Category.Colors.init(rawValue: oldCategory.color?.rawValue ?? "") ?? .blue,
icon: getCategoryIcon(oldIcon: oldCategory.icon)
)
// Remove old category
context.delete(oldCategory)
}
// Create new
let new = Transaction(
date: transaction.date,
action: action,
direction: direction,
amount: transaction.amount,
note: transaction.note,
category: category,
month: newMonth
)
// Remove old transaction from month
oldMonth.transactions?.removeAll(where: { $0.id == transaction.id })
// Delete transaction from context
context.delete(transaction)
// Add new transaction to new month
newMonth.transactions?.append(new)
}
// Remove old month
context.delete(oldMonth)
print("After looping through transactions and deleting old month")
print("Number of transactions in oldMonth: \(oldMonth.transactions?.count)")
print("Number of transactions in newMonth: \(newMonth.transactions?.count)")
// Insert new month
context.insert(newMonth)
print("Inserted new month into context")
}
// Save
try context.save()
}, didMigrate: { context in
print("In did migrate")
let newMonths = try context.fetch(FetchDescriptor<SchemaV2.Month>())
print("Number of new months after migration: \(newMonths.count)")
}
)
static var stages: [MigrationStage] {
[migrateV1toV2]
}
}
It seems to run fine until it gets the the line: try context.save()
. At this point it fails with the following line:
SwiftData/PersistentModel.swift:726: Fatal error: What kind of backing data is this? SwiftData._KKMDBackingData<Monthly.SchemaV1.Transaction>
Anyone know what I can do about this?