错误:NSArray 在访问全局变量和核心数据时被枚举抛出

Posted

技术标签:

【中文标题】错误:NSArray 在访问全局变量和核心数据时被枚举抛出【英文标题】:Error: NSArray was mutated while being enumerated thrown when accessing globals and Core Data 【发布时间】:2012-04-17 09:19:04 【问题描述】:

我有这段代码,用于在添加另一个对象时更新 Core Data 中的一些值:

//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++;

            

此代码给出错误:

'...在枚举时发生了变异'。

谁能解释为什么?另外,有没有更好的方法来做我想要实现的目标?

【问题讨论】:

【参考方案1】:

您看到的错误是准确的。问题是您在迭代集合时正在改变(更改)集合。基本上,您正在执行以下形式的操作:

for (Project *p in appDelegate.projects) 
   ...
   [p addObject: X]

这是不允许的。

一个简单的解决方案是创建一个您想要添加的对象的新集合,然后将它们添加到循环的外部的原始容器中。比如:

NSMutableArray *array = [NSMutableArray array];
for (Project *p in appDelegate.projects) 
   ...
   [array addObject:X];

[p addObjects:array];

顺便问一下,您是否在 Google 上搜索到错误文本“在枚举时发生了变异”?如果您仅通过谷歌搜索没有找到这个常见问题的答案,我会感到惊讶。

此外,在发布错误消息时,发布整行而不是部分内容会很有帮助。

【讨论】:

嗨,我在以下方法中遇到了同样的错误。你能建议我正确的方法.... for (int i = 0; i 嗨@NavnathMemane,我的回答非常清楚地描述了问题所在。阅读它并将其应用到您自己的代码中。 感谢@oculus。我很久以前就解决了上述问题。好吧,如果你能在下面的 SO ***.com/questions/16646039/… 上帮助我【参考方案2】:

您正在添加和删除 appDelegate.projects 中的项目,同时在此处的 for-each 循环中对其进行迭代:

[appDelegate.projects removeObjectAtIndex:count];
// ...
[appDelegate.projects addObject:tempProject];

appDelegate.categories 也是如此:

[appDelegate.categories removeObjectAtIndex:count];
// ...
[appDelegate.categories addObject:tempProject];

AFAIK,在这种情况下,您应该使用简单的 for 循环,并使用索引访问数组。

【讨论】:

以上是关于错误:NSArray 在访问全局变量和核心数据时被枚举抛出的主要内容,如果未能解决你的问题,请参考以下文章

全局变量/常量如何在 swift 中变得懒惰

核心数据可转换属性(NSArray)为空

低代码平台-宜搭的核心概念

带有核心数据对象的 NSArray 的单例 null

C++ 错误:尝试访问全局变量时变量未命名类型

为啥设置类变量 NSArray 需要我使用访问器方法?