CoreData和NSManagedObjectContext

时间:2012-10-17 18:23:11

标签: ios core-data nsmanagedobject nsmanagedobjectcontext

我有这个功能将对象从“fallbackstore”移动到iCloud存储,fallbackstore是存储iCloud不可用时保存的对象的存储。

底线,我需要将对象(及其关系)从一个上下文移动到另一个上下文。

但是我收到了这个错误:

*由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'Context已经有一个协调器;无法取代。 * 首先抛出调用堆栈:

在:

foodSuccess = [moc save:& localError];

有人知道我哪里出错(以及为什么)?提前谢谢!

    - (BOOL)seedStore:(NSPersistentStore *)store withPersistentStoreAtURL:(NSURL *)seedStoreURL error:(NSError * __autoreleasing *)error {
    BOOL success = YES;

    NSLog(@"%s", __func__);

    BOOL foodSuccess = YES;
    BOOL sportSuccess = YES;
    BOOL dailySuccess = YES;
    BOOL activitySuccess = YES;
    BOOL reportSuccess = YES;
    BOOL userSuccess = YES;
    BOOL ingredientSuccess = YES;

    NSUInteger batchSize = 5000;

    NSError *localError = nil;

    NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
    NSPersistentStoreCoordinator *seedPSC = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    NSDictionary *seedStoreOptions = @{ NSReadOnlyPersistentStoreOption : [NSNumber numberWithBool:YES] };
    NSPersistentStore *seedStore = [seedPSC addPersistentStoreWithType:NSSQLiteStoreType
                                                         configuration:nil
                                                                   URL:seedStoreURL
                                                               options:seedStoreOptions
                                                                 error:&localError];
    if (seedStore) {
        NSManagedObjectContext *seedMOC = [[NSManagedObjectContext alloc] init];
        [seedMOC setPersistentStoreCoordinator:seedPSC];

        // Food
        NSFetchRequest *fr = [NSFetchRequest fetchRequestWithEntityName:@"Food"];
        fr.relationshipKeyPathsForPrefetching = @[@"daily", @"ingredient", @"ingredients"];
        [fr setFetchBatchSize:batchSize];

        NSArray *foods = [seedMOC executeFetchRequest:fr error:&localError];
        NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [moc setPersistentStoreCoordinator:_psc];
        NSUInteger i = 1;
        for (Food *f in foods) {
            [self addFood:f toStore:store withContext:moc];
            if (0 == (i % batchSize)) {
                foodSuccess = [moc save:&localError];
                if (foodSuccess) {
                    [moc reset];
                } else {
                    NSLog(@"Error saving during seed (Food): %@", localError);
                    break;
                }
            }

            i++;
        }

        if ([moc hasChanges]) {
            foodSuccess = [moc save:&localError];
            [moc reset];
        }

        // Sport
        NSFetchRequest *fetchSports = [NSFetchRequest fetchRequestWithEntityName:@"Sport"];
        fetchSports.relationshipKeyPathsForPrefetching = @[@"activity"];
        fetchSports.fetchBatchSize = batchSize;

        NSArray *sports = [seedMOC executeFetchRequest:fetchSports error:&localError];
        NSManagedObjectContext *sportContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        sportContext.persistentStoreCoordinator = _psc;
        NSUInteger iSports = 1;
        for (Sport *s in sports) {
            [self addSport:s toStore:store withContext:sportContext];
            if (0 == (iSports % batchSize)) {
                sportSuccess = [moc save:&localError];
                if (sportSuccess) {
                    [moc reset];
                } else {
                    NSLog(@"Error saving during seed (Sport): %@", localError);
                    break;
                }
            }

            iSports++;
        }

        if ([sportContext hasChanges]) {
            sportSuccess = [sportContext save:&localError];
            [sportContext reset];
        }

        // Daily
        NSFetchRequest *fetchDailies = [NSFetchRequest fetchRequestWithEntityName:@"Daily"];
        fetchDailies.relationshipKeyPathsForPrefetching = @[@"food", @"user"];
        fetchDailies.fetchBatchSize = batchSize;

        NSArray *dailies = [seedMOC executeFetchRequest:fetchDailies error:&localError];
        NSManagedObjectContext *dailiesContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        dailiesContext.persistentStoreCoordinator = _psc;
        NSUInteger iDailies = 1;
        for(Daily *d in dailies) {
            [self addDaily:d toStore:store withContext:dailiesContext];
            if(0 == (iDailies % batchSize)) {
                dailySuccess = [dailiesContext save:&localError];
                if (dailySuccess) {
                    [dailiesContext reset];
                }
                else {
                    NSLog(@"Error saving during seed (Daily): %@", localError);
                    break;
                }
            }

            iDailies++;
        }

        if ([dailiesContext hasChanges]) {
            dailySuccess = [dailiesContext save:&localError];
            [dailiesContext reset];
        }

        // Ingredient
        NSFetchRequest *fetchIngredients = [NSFetchRequest fetchRequestWithEntityName:@"Ingredient"];
        fetchIngredients.relationshipKeyPathsForPrefetching = @[@"food", @"foods"];
        fetchIngredients.fetchBatchSize = batchSize;

        NSArray *ingredients = [seedMOC executeFetchRequest:fetchIngredients error:&localError];
        NSManagedObjectContext *ingredientsContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        ingredientsContext.persistentStoreCoordinator = _psc;
        NSUInteger iIngredients = 1;
        for(Ingredient *i in ingredients) {
            [self addIngredient:i toStore:store withContext:ingredientsContext];
            if(0 == (iIngredients % batchSize)) {
                ingredientSuccess = [ingredientsContext save:&localError];
                if (ingredientSuccess) {
                    [ingredientsContext reset];
                }
                else {
                    NSLog(@"Error saving during seed (Ingredient): %@", localError);
                    break;
                }
            }

            iIngredients++;
        }

        if ([ingredientsContext hasChanges]) {
            ingredientSuccess = [ingredientsContext save:&localError];
            [ingredientsContext reset];
        }

        // Activity
        NSFetchRequest *fetchActivities = [NSFetchRequest fetchRequestWithEntityName:@"Activity"];
        fetchActivities.relationshipKeyPathsForPrefetching = @[@"sport", @"user"];
        fetchActivities.fetchBatchSize = batchSize;

        NSArray *activities = [seedMOC executeFetchRequest:fetchActivities error:&localError];
        NSManagedObjectContext *activitiesContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        dailiesContext.persistentStoreCoordinator = _psc;
        NSUInteger iActivities = 1;
        for(Activity *a in activities) {
            [self addActivity:a toStore:store withContext:activitiesContext];
            if(0 == (iActivities % batchSize)) {
                activitySuccess = [activitiesContext save:&localError];
                if (activitySuccess) {
                    [activitiesContext reset];
                }
                else {
                    NSLog(@"Error saving during seed (Activity): %@", localError);
                    break;
                }
            }

            iActivities++;
        }

        if ([activitiesContext hasChanges]) {
            activitySuccess = [activitiesContext save:&localError];
            [activitiesContext reset];
        }

        // Report
        NSFetchRequest *fetchReports = [NSFetchRequest fetchRequestWithEntityName:@"Report"];
        fetchReports.relationshipKeyPathsForPrefetching = @[@"user"];
        fetchReports.fetchBatchSize = batchSize;

        NSArray *reports = [seedMOC executeFetchRequest:fetchReports error:&localError];
        NSManagedObjectContext *reportsContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        reportsContext.persistentStoreCoordinator = _psc;
        NSUInteger iReports = 1;
        for(Report *r in reports) {
            [self addReport:r toStore:store withContext:reportsContext];
            if(0 == (iReports % batchSize)) {
                reportSuccess = [reportsContext save:&localError];
                if (reportSuccess) {
                    [reportsContext reset];
                }
                else {
                    NSLog(@"Error saving during seed (Report): %@", localError);
                    break;
                }
            }

            iReports++;
        }

        if ([reportsContext hasChanges]) {
            reportSuccess = [reportsContext save:&localError];
            [reportsContext reset];
        }

        // User
        NSFetchRequest *fetchUsers = [NSFetchRequest fetchRequestWithEntityName:@"User"];
        fetchUsers.relationshipKeyPathsForPrefetching = @[@"activities", @"dailies", @"reports"];
        fetchUsers.fetchBatchSize = batchSize;

        NSArray *users = [seedMOC executeFetchRequest:fetchUsers error:&localError];
        NSManagedObjectContext *usersContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        usersContext.persistentStoreCoordinator = _psc;
        NSUInteger iUsers = 1;
        for(User *u in users) {
            [self addUser:u toStore:store withContext:usersContext];
            if(0 == (iUsers % batchSize)) {
                userSuccess = [usersContext save:&localError];
                if (userSuccess) {
                    [usersContext reset];
                }
                else {
                    NSLog(@"Error saving during seed (User): %@", localError);
                    break;
                }
            }

            iUsers++;
        }

        if ([usersContext hasChanges]) {
            userSuccess = [usersContext save:&localError];
            [usersContext reset];
        }

        // Result

        success = foodSuccess && sportSuccess && dailySuccess && ingredientSuccess && activitySuccess && reportSuccess && userSuccess;

    } else {
        success = NO;
        NSLog(@"Error adding seed store: %@", localError);
    }

    if (NO == success) {
        if (localError  && (error != NULL)) {
            *error = localError;
        }
    }

    return success;
}


    - (void)addFood:(Food *)food toStore:(NSPersistentStore *)store withContext:(NSManagedObjectContext *)moc
{
    NSEntityDescription *entity = [food entity];
    Food *newFood = [[Food alloc] initWithEntity:entity insertIntoManagedObjectContext:moc];

    newFood.alcol = food.alcol;
    newFood.amid = food.amid;
    newFood.bookmark = food.bookmark;
    newFood.calcium = food.calcium;
    newFood.cho = food.cho;
    newFood.cholesterol = food.cholesterol;
    newFood.complex = food.complex;
    newFood.copper = food.copper;
    newFood.dirty = food.dirty;
    newFood.edible = food.edible;
    newFood.fat = food.fat;
    newFood.fatMono = food.fatMono;
    newFood.fatPoli = food.fatPoli;
    newFood.fatSat = food.fatSat;
    newFood.fibre = food.fibre;
    newFood.iron = food.iron;
    newFood.kcal = food.kcal;
    newFood.lookback = food.lookback;
    newFood.magnesium = food.magnesium;
    newFood.name = food.name;
    newFood.note = food.note;
    newFood.phosphorus = food.phosphorus;
    newFood.potassium = food.potassium;
    newFood.pro = food.pro;
    newFood.recipe = food.recipe;
    newFood.recordUUID = (food.recordUUID == nil) ? [[[NSUUID alloc] init] UUIDString] : food.recordUUID;
    newFood.serving = food.serving;
    newFood.servingDesc = food.servingDesc;
    newFood.sodium = food.sodium;
    newFood.userAdd = food.userAdd;
    newFood.vitA = food.vitA;
    newFood.vitC = food.vitC;
    newFood.vitE = food.vitE;
    newFood.water = food.water;
    newFood.zinc = food.zinc;
    newFood.dosePeople = food.dosePeople;
    newFood.daily = food.daily;

    for(Ingredient *i in food.ingredients) {
        NSEntityDescription *entityIngredient = [i entity];
        Ingredient *newIngredient = [[Ingredient alloc] initWithEntity:entityIngredient insertIntoManagedObjectContext:moc];
        [newFood addIngredientsObject:newIngredient];
    }

    NSMutableSet *ing = [food mutableSetValueForKey:@"ingredient"];
    for(Ingredient *i in ing) {
        NSLog(@"%s Name: %@", __func__, i.food.name);

        NSEntityDescription *entityIngredient = [i entity];
        Ingredient *newIngredient = [[Ingredient alloc] initWithEntity:entityIngredient insertIntoManagedObjectContext:moc];
        [newFood addIngredientsObject:newIngredient];
    }


    [moc assignObject:newFood toPersistentStore:store];
}

1 个答案:

答案 0 :(得分:0)

您可能会或可能不会导致错误,但如果您使用NSPrivateQueueConcurrencyType初始化MOC,则应通过-performBlock:-performBlockAndWait:严格访问该MOC。请参阅此相关question