Reputation: 1555
I have this piece of code which I am using to update some values in Core Data when another object is added:
//Create new receipt
Receipt *receipt = [[Receipt alloc] init];
receipt.project = self.projectLabel.text;
receipt.amount = self.amountTextField.text;
receipt.descriptionNote = self.descriptionTextField.text;
receipt.business = self.businessNameTextField.text;
receipt.date = self.dateLabel.text;
receipt.category = self.categoryLabel.text;
receipt.paidBy = self.paidByLabel.text;
receipt.receiptImage1 = self.receiptImage1;
//Need to set this to 2
receipt.receiptImage2 = self.receiptImage1;
receipt.receiptNumber = @"99";
int count = 0;
int catCount = 0;
for (Project *p in appDelegate.projects)
{
if ([p.projectName isEqualToString:receipt.project]){
double tempValue = [p.totalValue doubleValue];
tempValue += [receipt.amount doubleValue];
NSString *newTotalValue = [NSString stringWithFormat:@"%.02f", tempValue];
NSString *newProjectName = p.projectName;
//remove entity from Core Data
NSFetchRequest * allProjects = [[NSFetchRequest alloc] init];
[allProjects setEntity:[NSEntityDescription entityForName:@"Project" inManagedObjectContext:appDelegate.managedObjectContext]];
[allProjects setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSError * error = nil;
NSArray * projectsArray = [appDelegate.managedObjectContext executeFetchRequest:allProjects error:&error];
//Delete product from Core Data
[appDelegate.managedObjectContext deleteObject:[projectsArray objectAtIndex:count]];
NSError *saveError = nil;
[appDelegate.managedObjectContext save:&saveError];
[appDelegate.projects removeObjectAtIndex:count];
NSLog(@"Removed project from Core Data");
//Insert a new object of type ProductInfo into Core Data
NSManagedObject *projectInfo = [NSEntityDescription
insertNewObjectForEntityForName:@"Project"
inManagedObjectContext:appDelegate.managedObjectContext];
//Set receipt entities values
[projectInfo setValue:newProjectName forKey:@"name"];
[projectInfo setValue:newTotalValue forKey:@"totalValue"];
if (![appDelegate.managedObjectContext save:&error]) {
NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
NSLog(@"Added Project to Core Data");
Project *tempProject = [[Project alloc] init];
tempProject.projectName = [projectInfo valueForKey:@"name"];
tempProject.totalValue = [projectInfo valueForKey:@"totalValue"];
[appDelegate.projects addObject:tempProject];
}
count++;
}
for (Category *c in appDelegate.categories){
if ([c.categoryName isEqualToString:receipt.category]){
double tempValue = [c.totalValue doubleValue];
tempValue += [receipt.amount doubleValue];
NSString *newTotalValue = [NSString stringWithFormat:@"%.02f", tempValue];
NSString *newCategoryName = c.categoryName;
//remove entity from Core Data
NSFetchRequest * allCategories = [[NSFetchRequest alloc] init];
[allCategories setEntity:[NSEntityDescription entityForName:@"Category" inManagedObjectContext:appDelegate.managedObjectContext]];
[allCategories setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSError * categoriesError = nil;
NSArray * categoriesArray = [appDelegate.managedObjectContext executeFetchRequest:allCategories error:&categoriesError];
//Delete product from Core Data
[appDelegate.managedObjectContext deleteObject:[categoriesArray objectAtIndex:catCount]];
NSError *categorySaveError = nil;
[appDelegate.managedObjectContext save:&categorySaveError];
[appDelegate.categories removeObjectAtIndex:catCount];
NSLog(@"Removed category from Core Data");
NSError * error = nil;
//Insert a new object of type ProductInfo into Core Data
NSManagedObject *categoryInfo = [NSEntityDescription
insertNewObjectForEntityForName:@"Category"
inManagedObjectContext:appDelegate.managedObjectContext];
//Set receipt entities values
[categoryInfo setValue:newCategoryName forKey:@"name"];
[categoryInfo setValue:newTotalValue forKey:@"totalValue"];
if (![appDelegate.managedObjectContext save:&error]) {
NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
NSLog(@"Added Category to Core Data");
Category *tempCategory = [[Category alloc] init];
tempCategory.categoryName = [categoryInfo valueForKey:@"name"];
tempCategory.totalValue = [categoryInfo valueForKey:@"totalValue"];
[appDelegate.categories addObject:tempCategory];
}
catCount++;
}
This code gives the error:
'...was mutated while being enumerated'.
Can anyone explain why? Also, is there a better approach to doing what I'm trying to achieve?
Upvotes: 1
Views: 2765
Reputation: 17014
The error you're seeing is accurate. The problem is that you're mutating (changing) a collection while iterating over it. Basically, you're doing something of the form:
for (Project *p in appDelegate.projects) {
...
[p addObject: X]
}
This isn't allowed.
One simple solution is to make a new collection of the objects you want to add, and then add them to the original container outside of your loop. Something like:
NSMutableArray *array = [NSMutableArray array];
for (Project *p in appDelegate.projects) {
...
[array addObject:X];
}
[p addObjects:array];
By the way, did you google for the error text "was mutated while being enumerated"? I'd be surprised if you didn't find the answer for this common problem just by googling.
Also, when posting an error message, it's helpful to post the full line, not just part of it.
Upvotes: 5
Reputation: 137292
You are adding and removing items from appDelegate.projects
while iterating over it in a for-each loop here:
[appDelegate.projects removeObjectAtIndex:count];
// ...
[appDelegate.projects addObject:tempProject];
And the same for appDelegate.categories
:
[appDelegate.categories removeObjectAtIndex:count];
// ...
[appDelegate.categories addObject:tempProject];
AFAIK, in such case you should use a simple for loop, and access the array with index.
Upvotes: 0