简体   繁体   中英

Core Data Migration and Versioning

I followed this guide to implement the core data migration and versioning in my non–document-based application. I did as reported driving but when but when I start the application tells me that the model I am opening is not supported. How can I fix this?

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator) {
        return _persistentStoreCoordinator;
    }

    NSManagedObjectModel *mom = [self managedObjectModel];
    if (!mom) {
        NSLog(@"%@:%@ No model to generate a store from", [self class], NSStringFromSelector(_cmd));
        return nil;
    }

    NSFileManager *fileManager = [NSFileManager defaultManager];

    NSURL *applicationFilesDirectory = [self applicationFilesDirectory];
    NSURL *storeURL = [[self applicationFilesDirectory] URLByAppendingPathComponent:@"Preventivi.storedata"];

    NSError *error = nil;
    //Turn on automatic store migration
    NSMutableDictionary *optionsDictionary = [NSMutableDictionary dictionary];
    [optionsDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
    NSDictionary *properties = [applicationFilesDirectory resourceValuesForKeys:@[NSURLIsDirectoryKey] error:&error];

    if (!properties) {
        BOOL ok = NO;
        if ([error code] == NSFileReadNoSuchFileError) {
            ok = [fileManager createDirectoryAtPath:[applicationFilesDirectory path] withIntermediateDirectories:YES attributes:nil error:&error];
            NSURL *defaultStoreURL = [[NSBundle mainBundle] URLForResource:@"Preventivi" withExtension:@"storedata"];
            if (defaultStoreURL) {
                [fileManager copyItemAtURL:defaultStoreURL toURL:storeURL error:NULL];
            }
        }
        if (!ok) {
            [[NSApplication sharedApplication] presentError:error];
            return nil;
        }
    } else {
        if (![properties[NSURLIsDirectoryKey] boolValue]) {
            // Customize and localize this error.
            NSString *failureDescription = [NSString stringWithFormat:@"Expected a folder to store application data, found a file (%@).", [applicationFilesDirectory path]];

            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            [dict setValue:failureDescription forKey:NSLocalizedDescriptionKey];
            error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:101 userInfo:dict];

            [[NSApplication sharedApplication] presentError:error];
            return nil;
        }
    }

    NSURL *url = [applicationFilesDirectory URLByAppendingPathComponent:@"Preventivi.storedata"];
    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
    if (![coordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]) {
        [[NSApplication sharedApplication] presentError:error];
        return nil;
    }
    _persistentStoreCoordinator = coordinator;

    return _persistentStoreCoordinator;
}

Can you tell where the Application throws the error? If its in the last lines, you could try to change the storeType NSXMLStoreType to NSSQLiteStoreType for example.

if (![coordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error])

to

if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:options error:&error]) 

For this you have also to change the suffix to "sqlite".

NSURL *url = [NSURL fileURLWithPath: [applicationFilesDirectory stringByAppendingPathComponent: @"Preventivi.sqlite"]]

and

NSURL *defaultStoreURL = [[NSBundle mainBundle] URLForResource:@"Preventivi" withExtension:@"sqlite"];

Or if you already have a solution, you could share this :) But comparing with my code, there are no real differences (only have an option more

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                         [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

and you don't use the options while adding the persistent store ^^ )

I hope this helps :)

It seems you've configured your Core Data stack to use auto migration. And continued changing model without using versioning.

You have to use versioned model. If you didn't create a model version before modifying it, auto migration won't work. In order to make auto migration work before every modificaton you should create a new model version and modify that new version.

For example you want to add couple attributes to an entity and add another entity, you:

  1. Create new model version (select model file, Editor->Add model version...);
  2. Select that new version and add attributes and entity.

And you should also say if you use configurations or not, as far as auto migration has issues with configurations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM