简体   繁体   中英

Multiple .xcdatamodeld core data files, how to save to correct one?

I've 3 core data managed objects files:

  1. CoreDataModel.xcdatamodeld
  2. CoreDataModel_Small.xcdatamodeld
  3. CoreDataModel_MyLocations.xcdatamodeld

In configured them like this:

AppDelegate.h:

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

/////// CoreDataModel_Small ///////
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext_small;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel_small;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator_small;

/////// CoreDataModel_MyLocations ///////
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext_MyLocations;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel_MyLocations;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator_MyLocations;

AppDelegate.m:

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataModel" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

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

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataModel.sqlite"];
    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
                              NSInferMappingModelAutomaticallyOption : @YES,
                              NSSQLiteManualVacuumOption : @YES};

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}

//////////// CoreDataModel_Small ////////////

- (NSManagedObjectContext *)managedObjectContext_small
{
    if (_managedObjectContext_small != nil) {
        return _managedObjectContext_small;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator_small];
    if (coordinator != nil) {
        _managedObjectContext_small = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext_small setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext_small;
}

- (NSManagedObjectModel *)managedObjectModel_small
{
    if (_managedObjectModel_small != nil) {
        return _managedObjectModel_small;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataModel_Small" withExtension:@"momd"];
    _managedObjectModel_small = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel_small;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator_small
{
    if (_persistentStoreCoordinator_small != nil) {
        return _persistentStoreCoordinator_small;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataSmall.sqlite"];
    NSError *error = nil;
    _persistentStoreCoordinator_small = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel_small]];

    NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
                              NSInferMappingModelAutomaticallyOption : @YES,
                              NSSQLiteManualVacuumOption : @YES};

    if (![_persistentStoreCoordinator_small addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        // abort();
    }

    return _persistentStoreCoordinator;
}

//////////// CoreDataModel_MyLocations ////////////

- (NSManagedObjectContext *)managedObjectContext_MyLocations
{
    if (_managedObjectContext_MyLocations != nil) {
        return _managedObjectContext_MyLocations;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator_MyLocations];
    if (coordinator != nil) {
        _managedObjectContext_MyLocations = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext_MyLocations setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext_MyLocations;
}

- (NSManagedObjectModel *)managedObjectModel_MyLocations
{
    if (_managedObjectModel_MyLocations != nil) {
        return _managedObjectModel_MyLocations;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataModel_MyLocations" withExtension:@"momd"];
    _managedObjectModel_MyLocations = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel_MyLocations;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator_MyLocations
{
    if (_persistentStoreCoordinator_MyLocations != nil) {
        return _persistentStoreCoordinator_MyLocations;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMyLocations.sqlite"];
    NSError *error = nil;
    _persistentStoreCoordinator_MyLocations = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel_MyLocations]];

    NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
                              NSInferMappingModelAutomaticallyOption : @YES,
                              NSSQLiteManualVacuumOption : @YES};

    if (![_persistentStoreCoordinator_MyLocations addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        // abort();
    }

    return _persistentStoreCoordinator;
}

And calling the correct context like this:

FOUNDATION_EXPORT NSManagedObjectContext *generateManagedObjectContext(CoreDataType type)
{
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];

    if (type == CoreDataTypeBig) {
        context.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator;
    }
    else if (type == CoreDataTypeSmall) {
        context.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator_small;
    }
    else if (type == CoreDataTypeMyLocations) {
        context.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator_MyLocations;
    }

    if ([NSThread isMainThread])    { [context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy]; }
    else                            { [context setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy]; }

    return context;
}

But I've an error in one of my methods, when deleting all objects from specific entity, I haven't had this problem before since I'd all managed objects in one .xcdatamodeld file and I've decided to separate them:

fetch request must have an entity

I think one of the problems is when I'm saving the context (in AppDelegate.m file), then the function stays as usual and I'm sure I need to somehow make it save to the correct NSManagedObjectContext .

EDIT 1:

The code that produce the error:

- (void)deleteTable
{
    NSManagedObjectContext *context = generateManagedObjectContext(CoreDataTypeMyLocations);

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:kCORE_DATA_LOCATION_ENTITY inManagedObjectContext:context];
    [fetchRequest setEntity:entity];

    NSError *error = nil;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
    if (fetchedObjects == nil) {
        NSLog(@"%s error: %@", __PRETTY_FUNCTION__, error.localizedDescription);
    }
    else {
        for (CoreDataMyLocation *mLoc in fetchedObjects) {
            [context deleteObject:mLoc];
        }

        if([context save:&error] == NO) {
            NSLog(@"%s error saving: %@\n%@", __PRETTY_FUNCTION__, error.localizedDescription, error.userInfo);
        }
    }
}

What that error is telling you is that when you do the fetch, entity is nil. It's hard to be certain why this is happening from the code. You appear to be:

  • Looking up persistentStoreCoordinator_MyLocations (which uses the data model at CoreDataModel_MyLocations.momd )
  • Looking up an entity whose name is stored in kCORE_DATA_LOCATION_ENTITY in a managed object context that uses that persistent store coordinator.
  • Fetching that entity

This implies that whatever is in kCORE_DATA_LOCATION_ENTITY does not match up with an entity name in CoreDataModel_MyLocations.momd . That could be as simple as a typo. The first thing to check is that the entity name matches exactly.

If the names match, the next step is a deeper validation of the Core Data stack. Does CoreDataModel_MyLocations.momd exist in the app bundle? Did persistentStoreCoordinator_MyLocations get initialized correctly? Verify that nothing in the stack is nil or otherwise missing.

Also, some people report that this problem is a side effect of having old app installs around, leading to some framework confusion. Make sure to remove any previous copies of the app from test devices and the simulator, and do a clean build.

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