Objective-c – Collection was mutated while being enumerated, UITableView

iphonensdictionaryobjective cuitableview

I have a filter button that presents a UITableView in a popover. I have my categories and an "All" button to denote that no filter is present like in iTunes.

I have a NSMutableDisctionary in my applicationDelegate class that I use to set the checkmarks. When the app starts, only All is selected, everything else is deselected. What I want is then when a row that is not "All" is selected, that row gets selected, and All gets deselected. Similarly, when All is selected, all the rows with checkmarks do not have checkmarks anymore, and only All is selected with a checkmark (like when the app starts). In my UITableView didSelectRowForIndexPath:, I did this:

MyAppAppDelegate *dmgr = (MyAppAppDelegate *)[UIApplication sharedApplication].delegate;
NSUInteger row = [indexPath row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

// All selected
if (row == 0) {
    for (NSString *key in dmgr.CategoryDictionary) {
        [dmgr.CategoryDictionary setObject:[NSNumber numberWithBool:NO] forKey:key];
    }
    [dmgr.CategoryDictionary setObject:[NSNumber numberWithBool:YES] forKey:@"All"];                
}

else {

    cell.accessoryType = UITableViewCellAccessoryCheckmark;
    NSString *key = [_categoriesArray objectAtIndex:row];
    BOOL valueAtKey = [[dmgr.CategoryDictionary valueForKey:key] boolValue];
    valueAtKey = !valueAtKey;       
    [dmgr.CategoryDictionary setObject:[NSNumber numberWithBool:valueAtKey] forKey:key];
}

Two questions. First is, I get this error when I select the first row (All):

Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFDictionary: 0x597b3d0> was mutated while being enumerated.

Where is the enumeration happening? I thought since I only select row 0, I could change the other rows as well, and not just the row 0. I'm not sure what to do about this here.

Second question is is this the way you'd want to update your model class? I wasn't sure if this was considered good MVC. Thanks.

Best Answer

The enumeration is the for-loop. You could iterate over a copy of the keys instead to avoid mutating the dictionary while enumerating it:

for (NSString *key in [dmgr.CategoryDictionary allKeys]) {
    //...
}