Tuesday, May 25, 2010

Setting value (object) while enumerating an NSMutableDictionary

Let's say you have an NSMutableDictionary instance which maps strings to numbers. For example, a list of stage names and the number of times the stage has been completed:

"level1" => 10
"level2" => 2
"final" => 1

I wanted to create a "clear data" function, so I enumerate the dictionary using the new foreach loop and set the value to 0 without adding or removing the key:

for (NSString *key in dictionary) {
    [dictionary setObject:[NSNumber numberWithInt:0] forKey:key];
}

This compiles fine, but a runtime error will occur:

Collection was mutated while being enumerated.

Unfortunately there is no API to modify the value even without adding or removing the key.

But, there is a solution: enumerate the keys instead of the dictionary. This works:

for (NSString *key in [dictionary allKeys]) {
    [dictionary setObject:[NSNumber numberWithInt:0] forKey:key];
}