jimbobuk
jimbobuk

Reputation: 1221

After Core Data lightweight migration to a version where a new attribute was added that attribute is nil

I'm trying to setup some test lightweight migrations within my app's core data, but I've come across a bit of an odd problem.

Between my version 2 and version 3 models of my app I've just added a new integer32 attribute. The attribute's default is set to 0 (the default that Xcode creates whenever you make a new attribute. I've tried testing this problem with the new attribute set to optional or not, it didn't make any difference.

I used Xcode to auto generate the my NSManagedObject subclass which contains the new property I've added.

I'm using UIManagedDocument to load my Core Data files and have set it up to perform an auto migration

NSDictionary *docOptions = @{
                        NSMigratePersistentStoresAutomaticallyOption : @YES,
                        NSInferMappingModelAutomaticallyOption : @YES
                        };
self.document.persistentStoreOptions = docOptions;

I take a live set of data with the current document set to version 2 and then change the app over to version 3. I run it and the document successfully opens so I presume the migration has worked correctly. Not sure how to get any errors out of this when it does fail, there's nothing in my logs.

Once I try to actually access the new attribute's NSNumber property of my NSManagedObject subclass for instances of the CoreData entity that I added I just find that the property is nil, rather than an NSNumber of default 0.

All the tutorials, documentation and questions I can find on this don't seem to say that I should have to do anything else to get this working.

If I work with the version 3 model cleanly and create new entities with that version then as you'd expect the new attribute is non-nil and so everything works ok. It's just migrating to this new version which doesn't seem to create the new attribute within the existing entity instances properly.

Anyone's help would be appreciated as always! Cheers.

Upvotes: 3

Views: 1222

Answers (1)

deekay
deekay

Reputation: 929

This is actually fairly simple, but may be a bit unintuitive.

The reason you see this new attribute value as 'nil' is because you most likely defined it as an 'optional' attribute. This means it is acceptable for it to be set to nil, so CoreData wont populate it during migration.

Default value will mater only while inserting new entities to the database.

I see few possible solutions:

  • Define this new attribute as non-optional (simple and clean).

Or - if you really need to keep this attribute as optional (tho, based on your question I doubt that's the case, also, this is not really a cleanest solution):

  • Perform 'content migration' is such manner:
    • Detect when you were migrating from version 2 to version 3 (you can use store metadata to track/keep current's content "version" number).
    • Query all existing entries, and populate data as you see fit.

Or:

  • Use more advanced migration mechanism than lightweight migration.

Upvotes: 4

Related Questions