Enable automatic easy migration of master data to NSPsistentDocument

ALM is excellent. But I can't get him to work on a project that uses Core Data with NSDocument. ALM seems to be disabled by default.

Fine For any normal project, you must add two corresponding parameters to the dictionary on this line:

if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) 

... but this line does not exist when using the CD with NSD (NSPersistentDocument hides the details, and I do not see how you can modify them).

The following method seems to give hope:

 configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error: 

... some people on the mailing lists (4+ years ago) report successful completion of this method, changing the options dictionary and calling it โ€œsuperโ€ again. Unfortunately, this did not work for me. I would suggest trying this if you have similar problems - then come back here if it still doesn't work :)

+4
source share
2 answers

Creating a new Cored-Data-with-NSDocument project from scratch, I tried an approach that didn't work initially, and this time it did great:

 -(BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error { NSMutableDictionary *newOptions = [NSMutableDictionary dictionaryWithDictionary:storeOptions]; [newOptions setValue:@"YES" forKey:NSMigratePersistentStoresAutomaticallyOption]; [newOptions setValue:@"TRUE" forKey:NSInferMappingModelAutomaticallyOption]; return [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newOptions error:error]; } 
+7
source

NB: I suspect the cause of my problems is that Xcode4 does not correctly update the private hashes, which it uses instead of version numbers, to track the version of the data model. I probably accidentally added something and then deleted it, and it changed the hash - my original model was so simple that it was easy to compare by eye, and there were no differences.

In addition, in the general case, the problem is that Xcode4 still does not properly handle CoreData projects - it by default creates CoreData models as โ€œversionsโ€ (a big improvement from Xcode3 that was doomed to always create useless models), but this - still does not process changes in the model - you must remember manually to update the version BEFORE you save any changes (otherwise the entire project migration will fail, forever, without exit).

Also, I couldn't find the โ€œrightโ€ solution if everything went wrong - there are too many missing parts from the Apple Core Data lib. Basically: NSPsistentDocument is incomplete, unsupported, as far as I can tell.


In the end, I went with the following BRUTAL workaround: instructed everyone with older versions to manually edit the CoreData repositories to claim that they were running the current version.

This works 100% because, unlike CoreData, my application is written to intelligently fix any obvious missing data when importing. This is trivial, but CoreData does not allow you to say "yes, I did it. OK. Go and open the file!"

  • in the old version: "save as XML"
  • gave them a new header to copy / paste to the top of the file. NB: Apple uses hashes instead of version numbers, which makes this look scary, even if it isn't. I donโ€™t understand why Apple ignores its own version system and uses hash instead?
  • in the new version: open the updated file
  • in the new version: "save"

... and because I override the NSManagedObject method:

-awakeFromInsert

and correcting any incorrect / missing data, steps 3 and 4 above "automatically" update the data.

I know that the โ€œrightโ€ way would be to create a matching model, but in most cases it was a huge overkill ... and Apple refused to load the old data in the first place. Thus, Core Data simply refused to even allow me to correct the data - although my code was happy to do it.

(all old projects are imported and exported correctly - no problem)

IMHO: CoreData really needs a design review at the end of Apple to fix all the extreme cases that they did not think about for the first time.


NB: quick warning: make sure you do not change CoreData variables inside awakeFromFetch. Apple temporarily disables change tracking before calling this method (which is ridiculous - it makes the method incompatible with the behavior of all the other "awakeFrom *").

Apple tip: inside awakeFromFetch, decide what you are going to change, then package and use something like this:

[self performSelector: @selector (myAwakeFromFetchFixItemX :) withObject: X afterDelay: 0.01];

... I just thought that I would add that for those who tried it - otherwise your import will work fine, but your export will silently include fixed data!

+1
source

All Articles