I referred to “What’s new in Core Data” in WWDC23, CoreData Documentation and other Posts related Staged Migrations.
I added three new model version through MyAppDataModel, using Hash Modifiers for Versioning.
(Because it caused Error for any version has same version checksum -> “The current model reference and the next model reference cannot be equal”)
<V1 -> V2>:
I added dateInTime attribute to Book Entity as LightweightMigration in MyAppDataModel.
<V2 -> V3>:
I want to set dateInTime attribute with Date type value, which is made by changing date attribute from String type to Date type.
And then want to set date attribute as nil.
As far as I know, Once NSStageMigrationManager is set to persistentStoreDescription’s option and just call persistentContainer.loadPersistentStore, Staged Migration will work.
But my staged migration isn’t work…
I’m wondering if there is something wrong with my code.
Any chance, If you need more information about my situation, please let me know!
guard let packageURL = Bundle.main.url(forResource: "MyAppDataModel", withExtension: ".momd") else {
fatalError("Failed to find file matched with name")
}
let v1ModelURL = packageURL.appending(component: "MyDataModel.mom")
let v2ModelURL = packageURL.appending(component: "MyDataModel 2.mom")
let v3ModelURL = packageURL.appending(component: "MyDataModel 3.mom")
guard let v1Model = NSManagedObjectModel(contentsOf: v1ModelURL),
let v2Model = NSManagedObjectModel(contentsOf: v2ModelURL),
let v3Model = NSManagedObjectModel(contentsOf: v3ModelURL) else {
fatalError("Failed to find model related to the URL")
}
let v1ModelReference = NSManagedObjectModelReference(model: v1Model, versionChecksum: v1Model.versionChecksum)
let v2ModelReference = NSManagedObjectModelReference(model: v2Model, versionChecksum: v2Model.versionChecksum)
let v3ModelReference = NSManagedObjectModelReference(model: v3Model, versionChecksum: v3Model.versionChecksum)
let v1ToV2 = NSCustomMigrationStage(migratingFrom: v1ModelReference, to: v2ModelReference)
// OR let v1ToV2 = NSLightweightMigrationStage([v1Model.versionChecksum])
v1ToV2.label = "V1 to V2: Add dateInTime attribute"
let v2ToV3 = NSCustomMigrationStage(migratingFrom: v2ModelReference, to: v3ModelReference)
customStage.label = "V2 to V3: Change date attribute type for all entities"
customStage.willMigrateHandler = { migrationManager, currentStage in
guard let container = migrationManager.container else {
fatalError("Failed to otionalize container")
}
let context = container.newBackgroundContext()
context.performAndWait {
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Book")
fetchRequest.predicate = NSPredicate(format: "date != nil")
do {
var fetchedResults: [NSManagedObject]
fetchedResults = try context.fetch(fetchRequest)
for book in fetchedResults {
guard let dateWithStringType = book.value(forKey: "date") as? String else {
fatalError("Failed to Cast as String")
}
let formatter = DateFormatter()
formatter.dateFormat = "yyyy.MM.dd E"
guard let dateWithDateType = formatter.date(from: dateWithStringType) else {
fatalError("Failed to parse as Date")
}
book.setValue(dateWithDateType, forKey: "dateInTime")
book.setValue(nil, forKey: "date")
}
try context.save()
} catch {
fatalError("Failed to Fetch Or Save: (error.localizedDescription)")
}
}
}
let migrationManager = NSStagedMigrationManager([v1ToV2, v2ToV3])
let persistentContainer = NSPersistentContainer(name: "MyAppDataModel")
guard let storeDescription = persistentContainer.persistentStoreDescriptions.first else {
fatalError("Failed to get a first desciption")
}
storeDescription.setOption(migrationManager, forKey: NSPersistentStoreStagedMigrationManagerOptionKey)
persistentContainer.loadPersistentStores { description, error in
if let error = error {
fatalError("Failed to load persistent store: (error.localizedDescription)")
}
}
user15256852 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.