Core Data migration failing with error: Failed to save new store after first pass of migration - iphone

In the past I had already implemented successfully automatic migration from version 1 of my data model to version 2. Now, using SDK 3.1.3, migrating from version 2 to version 3 fails with the following error:
Unresolved error Error Domain=NSCocoaErrorDomain Code=134110 UserInfo=0x5363360 "Operation could not be completed. (Cocoa error 134110.)", {
NSUnderlyingError = Error Domain=NSCocoaErrorDomain Code=256 UserInfo=0x53622b0 "Operation could not be completed. (Cocoa error 256.)";
reason = "Failed to save new store after first pass of migration.";
}
I have tried automatic migration using NSMigratePersistentStoresAutomaticallyOption and NSInferMappingModelAutomaticallyOption and also migration using only NSMigratePersistentStoresAutomaticallyOption, providing a mapping model from v2 to v3.
I see the above error logged, and no object is available in the application. However, if I quit the application and reopen it, everything is in place and working.
The Core Data methods I am using are the following ones
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
NSString *path = [[NSBundle mainBundle] pathForResource:#"MYAPP" ofType:#"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
return managedObjectModel;
}
- (NSManagedObjectContext *) managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return managedObjectContext;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"MYAPP.sqlite"]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Handle error
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
return persistentStoreCoordinator;
}
In the simulator, I see that this generates a MYAPP~.sqlite files and a MYAPP.sqlite file. I tried to remove the MYAPP~.sqlite file, but
BOOL oldExists = [[NSFileManager defaultManager] fileExistsAtPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"MYAPP~.sqlite"]];
always returns NO. Any clue? Am I doing something wrong?
Thank you in advance.

I ran into this as well and after reading as much Apple docs and web postings as I could find there didn't seem to be an answer. In my case the manual migration was working as well but when I went to open up a new coordinator it would give the same error you had. I finally decided to go back to my last working version of the data model and do a series of small changes/versions and see where it broke the auto-migration capabilities to drill further into it and it turned out it didn't. Now I can add entities, attributes and relationships without issue and they auto-migrate. Any chance you deleted an interim version of the datamodel?

For what it's worth, the Magical Record Core Data utility package includes this hack:
[coordinator MR_addAutoMigratingSqliteStoreNamed:storeFileName];
//HACK: lame solution to fix automigration error "Migration failed after first pass"
if ([[coordinator persistentStores] count] == 0)
{
[coordinator performSelector:#selector(MR_addAutoMigratingSqliteStoreNamed:) withObject:storeFileName afterDelay:0.5];
}
You might try something similar. I have been unable to find an explanation of what the problem is, though, or why just retrying it would work.

Related

Core data update model with app update?

everyone who work with Core Data know the message "the model used to open the store is incompatible with the one used to create the store".
Then I have to delete my app from simulator, and rebuilding it again.
My question is if I submit an app v 1.0, then add some entities to core data in v 1.1, does this mean that the users of 1.0 who updated to 1.1 will have their data cleared up?
You will need to create a new model version for your model, and migrate the database. You can do a lightweight migration if your model changes are within the required changes. If not, you will need to tell core data how to migrate your data. Check the migration documentation: http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CoreDataVersioning/Articles/Introduction.html
In your case it sounds like a simple extension to your old data model. If you just really add some new entities or even new classes then the so called leightweight migration is the right way to go for you.
Actually in this case you almost do not have anything to do, but create your second model IN ADDITION to your original model. It is important, that you have BOTH model, then the app will just load your 1st version without any problems as well as the new version.
Don't forget to mark your new model as the new one!
Try to be careful when creating the new model, since deleting a model is a real hassle.
Your code will look very similar to this:
-(NSManagedObjectContext *)managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *lC = [self persistentStoreCoordinator];
if (lC != nil) {
managedObjectContext =[[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: lC];
}
return managedObjectContext;
}
- (NSPersistentStoreCoordinator *) persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
// Allow inferred migration from the original version of the application.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"DBName.sqlite"]];
NSError *error = nil;
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl
options:options error:&error]){
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
return persistentStoreCoordinator;
}
- (NSManagedObjectModel *) managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
return managedObjectModel;
}

iOS: EXC_ARM_DA_ALIGN in generated CoreData code

I feel like I'm starting to lose my sanity over this issue.
I've begun work on a CoreData iOS app, using the generated CoreData code that the SDK provides. My issue arises whenever I attempt to instantiate a new instance of an entity so that I can save it.
Here's the instantiation code I have, per the Apple CoreData tutorial, inside my AppDelegate (I've moved a bunch of my code there just to try to debug this issue):
NSManagedObjectContext* context = [self managedObjectContext];
if (!context)
{
NSLog(#"Error"); // I'm not too concerned about my error handling just yet
}
Right after that, here's the line that produces the error I'm experiencing:
Vehicle* vehicle = (Vehicle*)[NSEntityDescription insertNewObjectForEntityForName:#"Vehicle" inManagedObjectContext:context];
The error in question is:
Thread 1: EXC_BAD_ACCESS (code=EXC_ARM_DA_ALIGN address=0xdeadbeef)
All in all, I don't really know what that means other than there's a memory alignment issue (common with ARMv7?) and the resources I've found on Google haven't helped me in the slightest.
The only other relevant piece of code is the 'managedObjectContext' method provided by Xcode when it generates the project, because that's what generated the managedObjectContext in the first place:
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
Like I said, I'm way out of my depth here. Can anyone offer a bit of clarity as to how I could possibly resolve this?
It is likely that __managedObjectContext was not initialized (hence has value of 0xdeadbeef) which cause EXC_ARM_DA_ALIGN as side effect when try to read value from it.
#Kenny Winker
EXC_ARM_DA_ALIGN is normally come from access pointer value that is not actual type. e.g.
char buf[8];
double d = *((double *)buf); // this may cause EXC_ARM_DA_ALIGN
but it may also be caused invalid valid in pointer, which in this case, 0xdeadbeef. e.g.
double *ptr; // not initialized
double d = *ptr; // this is undefined behaviour, which may cause EXC_ARM_DA_ALIGN or other error
It is generally hard to debug these kind of bugs, here are some tips:
Check all pointer cast (i.e. (double *)(void *)ptr) and try to avoid them when possible.
Make sure everything is initialized.
When it crashed, find out which variable cause it crash and try to trace back to find out where is the value come from. Use debugger to watch a memory location can be helpful to find out all changes to a variable.
I thought it might be helpful to show a core data stack that is in operation. I will also show a part of the object diagram..
pragma mark -
#pragma mark Core Data stack
/**
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *)managedObjectContext {
// NSLog(#"%s", __FUNCTION__);
if (managedObjectContext_ != nil) {
return managedObjectContext_;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext_ = [[NSManagedObjectContext alloc] init];
[managedObjectContext_ setPersistentStoreCoordinator:coordinator];
}
return managedObjectContext_;
}
/**
Returns the managed object model for the application.
If the model doesn't already exist, it is created from a starter file.
*/
- (NSManagedObjectModel *)managedObjectModel {
//NSLog(#"%s", __FUNCTION__);
if (managedObjectModel_ != nil) {
return managedObjectModel_;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"DreamCatching" withExtension:#"mom"];
managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return managedObjectModel_;
}
/**
Returns the persistent store coordinator for the application.
If the coordinator doesn't already exist, it is created and the application's store added to it.
*/
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
//NSLog(#"%s", __FUNCTION__);
if (persistentStoreCoordinator_ != nil) {
return persistentStoreCoordinator_;
}
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:#"DreamCatching.sqlite"];
// If the expected store doesn't exist, copy the default store.
//COMMENT / UNCOMMENT THIS TO LOAD / NOT LOAD THE STARTER FILE.
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:storePath]) {
NSError *error;
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:#"Starter" ofType:#"sqlite"];
if ([[NSFileManager defaultManager] copyItemAtPath:defaultStorePath toPath:storePath error:&error])
NSLog(#"Copied starting data to %#", storePath);
else
NSLog(#"Error copying default DB to %# (%#)", storePath, error);
}
// to below here
NSURL *storeURL = [NSURL fileURLWithPath:storePath];
NSError *error = nil;
persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Error - App Delegate Creating DB %#, %#", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator_;
}
#pragma mark -
#pragma mark Application's Documents directory
/**
Returns the path to the application's Documents directory.
NB SETTINGS ARE NOT IN THIS DIRECTORY, THEY ARE IN THE APPS BUNDLE. CONTROL-CLICK THE APP TO SEE CONTENTS, CONTROL-CLICK THE BUNDLE TO SEE THE PREFS
*/
- (NSString *)applicationDocumentsDirectory {
//NSLog(#"%s", __FUNCTION__);
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
and the model:

Core Data Error: Persistent store coordinator is not getting the File. It is the Phase appDelegate.Below the bolded phase has error.

In My Application
I have one sqlite file CoreDataBountyHunter.sqlite
I am using the Core Data Object Model to connect this sqlite file.
As it is the Basic application I have got the error before fetching the data or actual code part. I have got the error like Persistent store coordinator can not connect to file or Model.
1) visits the view will appear part
NSManagedObjectContext *moc=appDelegate.managedObjectContext. Part
from that it goes to the
2) Some code which shows File is Exists
3) then it goes to the Below code of persistent store coordinator from which it calls the Function of MANAGED OBJECT MODEL which is present at next code here...
After returning back to persistent coordinator in if condition it has got error and aborting so please help
-
//1--------
(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
NSURL *storeURL=[[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"CoreDataBountyHunter.sqlite"];
NSLog(#"%#",storeURL);
NSError *error = nil;
**__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])**
{
Typical reasons for an error here include:
* The persistent store is not accessible;
* The schema for the persistent store is incompatible with current managed object model.
Check the error message to determine what the actual problem was.
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
**abort();** I have error at this place
} ``
return __persistentStoreCoordinator;
}
enter code here
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil)
{
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"CoreDataBountyHunter" withExtension:#"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
//-------------------------------------------------------------------------------------
Actually it is a total mess with how Core data is working with different paths to read Write data so please explain also. Thanks Why I am getting the error at this place.
So, After visiting the MANAGED OBJECT MODEL CODE IT GOES TO THE PERSISTENT COORDINATOR SO AT THIS PLACE IT SHOULD HAVE SOME MESS...
Any time If you change the .xcdamodel file then your application will crash surely.
Can you try to this code in core data:
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel;
}
No need to shout...
What happens when you use the more usual
+ (NSManagedObjectModel *)mergedModelFromBundles:(NSArray *)bundles
as in
- (NSManagedObjectModel *)managedObjectModel
{
if (!__managedObjectModel)
{
__managedObjectModel = [[NSManagedObjectModel mergedModelFromBundle:nil] retain];
}
return __managedObjectModel;
}
Unless you have multiple models it's slightly cleaner
A suggestion:
Whenever you want to make changes in the core data file then don' do it directly in the same file or version of core data. Best practice is to follow the Modal versions for core data. It will prevent the crashes and also It will be very helpful in case when your app is already in production.
For modal version, refer this link. For more description please research on Google.
https://developer.apple.com/library/ios/recipes/xcode_help-core_data_modeling_tool/Articles/creating_new_version.html

Core Data - Migration question?

I am trying to do a migration
I have 2 versions of model
1.xcdatamodel
2.xcdatamodel
I created a mapping model from version 1 to 2
1to2.xcmappingmodel
The problem is that it can't find the migration model that I created so mappingModel always gets nil.
Is there anything I have to do to specify what mappingModel it ahould use?
target = [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:modelPath]];
//target and source are initialized correctly
mappingModel = [NSMappingModel mappingModelFromBundles:nil forSourceModel:source destinationModel:target];
It might be that you changed one of your models after creating the mapping model.
Even if a change does not seem relevant it will change the hash value of the model which is used for finding the appropriate mapping model.
At least I've been bitten by this just now :-)
If you've already created a mapping model from 1.xcdatamodel to 2.xcdatamodel, and properly configured it, then you should be able to do something like this: [Note: the key is specifying NSMigratePersistentStoresAutomaticallyOption]
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (persistentStoreCoordinator)
return persistentStoreCoordinator;
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"MyStore.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, nil];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeUrl
options:options
error:&error])
{
// Handle error
NSLog(#"Error adding persistent store...%#", error);
// Handle the error.
NSLog(#"Failed to save to data store: %#", [error localizedDescription]);
NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors != nil && [detailedErrors count] > 0)
{
for(NSError* detailedError in detailedErrors)
{
NSLog(#" DetailedError: %#", [detailedError userInfo]);
}
}
else
{
NSLog(#" %#", [error userInfo]);
}
}
else
{
DLog(#"Persistent store added without incident, apparently.");
}
return persistentStoreCoordinator;
}
To answer the original question, your code looks alright but I'm not why you passed nil as the bundles parameter. The documentation doesn't say one can. So:
NSArray *theBundles = [NSArray arrayWithObject:[NSBundle mainBundle]];
mappingModel = [NSMappingModel mappingModelFromBundles:theBundles
forSourceModel:source
destinationModel:target];
If you pass nil as bundle parameter, it will take [NSBundle mainBundle].
[To response to question of Elise van Looij]

Core Data Lightweight Migration - Cant Merge Models

I need to add some attributes to my core data model and I am having a terrible time getting lightweight migration to work!
I keep getting the error "Cant merge models with two different entities named blah".
Here's what I've done ...
Added this code to my app delegate.
(NSPersistentStoreCoordinator*)persistentStoreCoordinator {
//blah blah
NSDictionary* options =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
//blah blah
return _persistentStoreCoordinator;
}
Clicked on my data model, went to Design > Data Model > Add Model Version.
Made my changes to the one with the LOWEST number, basically adding a few attributes.
Deleted all the managed files produced from my previous model, sent them to trash, then created new ones from the new model.
Cleaned all targets.
Build and go.
ERROR.
Please please help. I've tried the above in numerous different ways, and loads of other stuff, each time going back to a clean copy of my project and starting again, and nothing has got me past this error.
Thanks!
Well, once again, another 6 hours of my life completely wasted because Apple are a bunch of ... well, I'll stop there.
Anyway, thanks to this lovely person: http://linkroller.com/fullpage/ad/13754/?http://iphonedevelopment.blogspot.com/2009/09/core-data-migration-problems.html I was able to solve the problem.
You follow the steps I already followed, then you need to find the following method:
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel;
}
and change it to:
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
NSString *path = [[NSBundle mainBundle] pathForResource:#"Foo" ofType:#"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
return managedObjectModel;
}
where foo is the name of you xcdatamodeld file.
AAAAAARGH.
I had fixed the core data migration
pls follwing this steps
Go AppDelegate.m write function
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
NSString *databaseFilePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"sampleiOS.sqlite"];
NSURL *storeUrl = [NSURL fileURLWithPath: databaseFilePath];
NSDictionary *_option = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:_option error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
return __persistentStoreCoordinator;
}
then select example.xcdatamodeld file
click the Editor menu on the top => add model version => create the new model version "example 2.xcdatamodel" then click finish button.
now show two core data model version one is source "example.xcdatamodel" another one is destination "example 2.xcdatamodel".
now add an attribute or entity in your new version datamodel "example 2.xcdatamodel". then click the group data model "example.xcdatamodeld". After that set current version to be newly created data model "example 2.xcdatamodel".
How to set current Version
select show utilities => show inspector => versioned core data model . then set current version.