0

I faced "Collection <_NSFaultingMutableSet: 0x7fac9c011190> was mutated while being enumerated" issue.

I know what it means, I found it on SO. I spotted the line which causes this exception. But I still can't get what exactly I'm mutating here. Could you please help me figure that out?

- (void)addEntitiesObject:(Entity *)value {
    for (Group* group in value.groups) {
        Group* groupToAddObjectTo = nil;
        for (Group* tabGroup in self.tab.groups) {
            if (group.title == tabGroup.title) {
                groupToAddObjectTo = tabGroup;
            }
        }
        if (!groupToAddObjectTo)
            groupToAddObjectTo = [self.fetchController createGroup];

        groupToAddObjectTo.title = group.title;
        [groupToAddObjectTo addEntitiesObject:value]; //THIS LINE IS A TROUBLE
        [self.tab addGroupsObject:groupToAddObjectTo];
    }
}

The method addEntitiesObject that causes a problem is generated by XCode with "Create NSManagedObject subclass...". I never define it.

Method "createGroup" only inserts new Group in CoreData with

    Group* group = (Group*)[NSEntityDescription insertNewObjectForEntityForName:@"Group" inManagedObjectContext:self.managedObjectContext];

and returns the group.

So my point is that I'm not using groupToAddObjectTo while it is in the loop where it is assigned to an element of NSSet, so what's the problem here?

rightaway717
  • 2,631
  • 3
  • 29
  • 43
  • where is 'addEntitiesObject' defined and does it modify value or value.groups? since you are iterating over value.groups, that would be a problem. – RobP Dec 10 '14 at 06:25
  • @RobP I'm not defining it. It's declared by XCode in Groups class. I never define it, as it might be defined by CoreData. So I have no idea what it really does under the hood. – rightaway717 Dec 10 '14 at 06:30
  • Do you have an inverse relationship from the group back to the `value.groups`? If so, this will cause your problem because when you add value to the group, value.groups will be mutated – Paulw11 Dec 10 '14 at 06:38
  • @Paulw11 self.tab.groups is NSSet, self.tab is NSManagedObject. And yes, it does have a inverse relationship. Let me check, whether it works, if I remove inverse relationships. – rightaway717 Dec 10 '14 at 06:41
  • @Paulw11 The crash has gone. So you were right, that was the issue. Could you please make it an answer, so I could accept it. I think others will benefit from it too. Thank you very much, I appreciate your help! – rightaway717 Dec 10 '14 at 06:51

1 Answers1

2

If you have an inverse relationship from groups back to the value entity, then adding the entity to a group will modify the value.groups property - which will cause your error as your outer loop is enumerating value.groups.

Either remove the inverse relationship, or if you need to keep it, copy the value.groups property and enumerate the copy.

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • Can you please explain it more or can you please show a simple example? – Wide Angle Technology Mar 02 '20 at 08:34
  • Which part needs more explanation? If you mutate a collection while you are iterating it, you get an exception. In the question, the code is adding a new `Group` entity in some cases. It then sets a relationship from that group to the `value` entity. Since there is an inverse relationship, Core Data updates the `value` entity's `groups` set to refer to the new `Group` - This is the set that is being enumerated by the outer `for` loop, so an exception is thrown – Paulw11 Mar 02 '20 at 09:52