我有这个功能,可以将对象从“fallbackstore”移动到 iCloud 商店,fallbackstore 是当 iCloud 不可用时保存对象的商店。
底线,我需要将对象(及其关系)从一个上下文移动到另一个上下文。
但我收到了这个错误:
* 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“上下文已经有一个协调器;无法替代。*首先抛出调用栈:
上:
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];
}