user339946
user339946

Reputation: 6119

Can't update an NSMutableDictionary value from within a for-in loop?

I'm having a weird issue with updating an NSMutableDictionary value. I'm running a for-in loop, everything is retrieved fine, and my math is fine.

The problem lies when I try to update my dictionary with the setValue: forKey: method.

for(NSString *key in self.planetDictionary){
         if(![key isEqualToString:planet]){ 

             * * *
            //do some math and stuff, create an NSNumber:
             NSNumber *update = [NSNumber numberWithFloat:updatedProbability];

             //Problem code, EXC_BAD_ACCESS here:
             [self.planetDictionary setValue:update forKey:key];
        }
    }

I get EXC_BAD_ACCESS crashes. I can confirm everything else is fine, its just the single line where I try to update the value.

What's going on? Thanks

Upvotes: 2

Views: 2499

Answers (3)

JRG-Developer
JRG-Developer

Reputation: 12663

You're not allowed to mutate an object that you're fast enumerating. It will crash every time. As a work around, you can make a copy first:

NSDictionary *dictionary = [self.planetDictionary copy];

for (NSString *key in dictionary) {
     if (![key isEqualToString:planet]) {              
         NSNumber *update = [NSNumber numberWithFloat:updatedProbability];
         [self.planetDictionary setValue:update forKey:key];
    }
}

Alternatively, if you have large objects in your dictionary (that conform to NSCopying, or else it would just be a shallow copy and won't matter very much), and hence you don't want to copy all the objects, then you could simply copy the keys (as an array) and enumerate them like this:

NSArray *keysCopy = [[self.planetDictionary allKeys] copy];

for (NSString *key in keysCopy) {
    if (![key isEqualToString:planet]) { 
        NSNumber *update = [NSNumber numberWithFloat:updatedProbability];
        [self.planetDictionary setValue:update forKey:key];
    }
}

Upvotes: 8

sixthcent
sixthcent

Reputation: 1160

You cannot update it while using it in for loop. Use a copy of the dictionary keys to use in for loop and update the original inside the for loop.

Upvotes: 2

RegularExpression
RegularExpression

Reputation: 3541

Looks like you're mutating it while enumerating it.

You can't change the NSDictionary while you're looping through it.

You might want to make a copy of it before the loop and enumerate the copy while you change the original.

Upvotes: 2

Related Questions