Custom Migration #116

Closed
opened 2025-12-29 15:24:51 +01:00 by adam · 3 comments
Owner

Originally created by @tosbaha on GitHub (Jan 6, 2017).

Hi,
I am in the process of upgrading my stack I need to do some migration. Lightweight migration works but leaves a property that I don't need it any more. I am sorry if this issue is not relevant. I checked the documentation but I only saw reference to lightweight migration. How can I do following migration with CoreStore?

Old Model

company Int16 (raw value of Company enum)
id String

New Model

slug String (string value based on Company)
renamedId (renamed from id)

I did the renaming by using Data Model inspector and using id as Renaming ID

My Current code with my old CoreData stack is like below which does the migration but leaves company attribute in new model.

func updateCoreDataIfNeeded(){
    let appDirectory = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "myidentifier")!
    let url = appDirectory.appendingPathComponent("MyModel.sqlite")
    guard let model = NSManagedObjectModel(contentsOf:Bundle.main.url(forResource: "MyModel", withExtension: "momd")!) else {
        return
    }
    do {
        let metaData = try NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: url)
        if (!model.isConfiguration(withName: nil, compatibleWithStoreMetadata: metaData) ) {
            //Model is not compatible
            updateCoreData()
        } else {
            print("No migration needed")
        }
    } catch {
        print(error)
        return
    }
}

func updateCoreData() {

    do {
            guard let kargos = try CoreDataHelper.sharedInstance.fetch("MyModel") as? [MyModel] else { return }
            for kargo in kargos {
                if (kargo.slug == "") {
                    print("Slug doesnt exist")
                    kargo.slug = Company(rawValue: Int(kargo.company))?.slug ?? Company.testpost.slug
                }
            }
            CoreDataHelper.sharedInstance.save()
            print("Update finished!")
        } catch {
            print(error)
            print("Update Error!")
        }
}
Originally created by @tosbaha on GitHub (Jan 6, 2017). Hi, I am in the process of upgrading my stack I need to do some migration. Lightweight migration works but leaves a property that I don't need it any more. I am sorry if this issue is not relevant. I checked the documentation but I only saw reference to lightweight migration. How can I do following migration with CoreStore? Old Model === ``` company Int16 (raw value of Company enum) id String ``` New Model === ``` slug String (string value based on Company) renamedId (renamed from id) ``` I did the renaming by using Data Model inspector and using `id` as Renaming ID My Current code with my old CoreData stack is like below which does the migration but leaves company attribute in new model. ```swift func updateCoreDataIfNeeded(){ let appDirectory = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "myidentifier")! let url = appDirectory.appendingPathComponent("MyModel.sqlite") guard let model = NSManagedObjectModel(contentsOf:Bundle.main.url(forResource: "MyModel", withExtension: "momd")!) else { return } do { let metaData = try NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: url) if (!model.isConfiguration(withName: nil, compatibleWithStoreMetadata: metaData) ) { //Model is not compatible updateCoreData() } else { print("No migration needed") } } catch { print(error) return } } func updateCoreData() { do { guard let kargos = try CoreDataHelper.sharedInstance.fetch("MyModel") as? [MyModel] else { return } for kargo in kargos { if (kargo.slug == "") { print("Slug doesnt exist") kargo.slug = Company(rawValue: Int(kargo.company))?.slug ?? Company.testpost.slug } } CoreDataHelper.sharedInstance.save() print("Update finished!") } catch { print(error) print("Update Error!") } } ```
adam added the question label 2025-12-29 15:24:51 +01:00
adam closed this issue 2025-12-29 15:24:51 +01:00
Author
Owner

@JohnEstropia commented on GitHub (Jan 6, 2017):

@tosbaha The setup code for lightweight and custom migrations in CoreStore is the same. See
https://github.com/JohnEstropia/CoreStore#progressive-migrations
where you have to provide a MigrationChain to the DataStack.

For custom migrations, CoreStore will look for a .xcmappingmodel file in your bundle for the source and destination model versions. If CoreStore finds one it will use that mapping, if it doesn't find one it will try to use lightweight migration as a last resort.

@JohnEstropia commented on GitHub (Jan 6, 2017): @tosbaha The setup code for lightweight and custom migrations in CoreStore is the same. See https://github.com/JohnEstropia/CoreStore#progressive-migrations where you have to provide a `MigrationChain` to the `DataStack`. For custom migrations, CoreStore will look for a *.xcmappingmodel* file in your bundle for the source and destination model versions. If CoreStore finds one it will use that mapping, if it doesn't find one it will try to use lightweight migration as a last resort.
Author
Owner

@tosbaha commented on GitHub (Jan 6, 2017):

Thanks for quick reply. I did following but it seems it is crashing. Could you tell me why ?

import Foundation
import CoreData


class KargoCDV1ToV2Policy:NSEntityMigrationPolicy {
    
    func valueFor(company:NSNumber) -> String {
        let company = Company(rawValue: Int(company))
        return company?.slug  ?? Company.testpost.slug
    }
}

screen shot 2017-01-06 at 3 02 30 pm
screen shot 2017-01-06 at 3 02 57 pm

I get

-[Kargotakip.KargoCDV1ToV2Policy valueFor:]: unrecognized selector sent to instance 0x60000000dc00

I also tried FUNCTION($entityPolicy, "valueForcompany:" , $source.company) again I get

-[Kargotakip.KargoCDV1ToV2Policy valueForcompany:]: unrecognized selector sent to instance 0x60000000dc00

I am using Swift 3. Is there a breaking change?

EDIT: If I change function to

func valueFor(_ comp:NSNumber) -> String {
        let company = Company(rawValue: Int(comp))
        return company?.slug  ?? Company.testpost.slug

    }


Then it worked. 🤷‍♂️

@tosbaha commented on GitHub (Jan 6, 2017): Thanks for quick reply. I did following but it seems it is crashing. Could you tell me why ? ```swift import Foundation import CoreData class KargoCDV1ToV2Policy:NSEntityMigrationPolicy { func valueFor(company:NSNumber) -> String { let company = Company(rawValue: Int(company)) return company?.slug ?? Company.testpost.slug } } ``` ![screen shot 2017-01-06 at 3 02 30 pm](https://cloud.githubusercontent.com/assets/971530/21717321/e2fd6f3a-d418-11e6-973c-fb3ce39b1c51.png) ![screen shot 2017-01-06 at 3 02 57 pm](https://cloud.githubusercontent.com/assets/971530/21717320/e2fd2052-d418-11e6-8381-e4e998e1a75b.png) I get > -[Kargotakip.KargoCDV1ToV2Policy valueFor:]: unrecognized selector sent to instance 0x60000000dc00 I also tried FUNCTION($entityPolicy, "valueForcompany:" , $source.company) again I get > -[Kargotakip.KargoCDV1ToV2Policy valueForcompany:]: unrecognized selector sent to instance 0x60000000dc00 I am using Swift 3. Is there a breaking change? EDIT: If I change function to ``` func valueFor(_ comp:NSNumber) -> String { let company = Company(rawValue: Int(comp)) return company?.slug ?? Company.testpost.slug } ``` Then it worked. 🤷‍♂️
Author
Owner

@JohnEstropia commented on GitHub (Jan 7, 2017):

Glad it worked for you :) I'm closing this issue now but if you have other questions feel free to ask!

@JohnEstropia commented on GitHub (Jan 7, 2017): Glad it worked for you :) I'm closing this issue now but if you have other questions feel free to ask!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/CoreStore#116