0

I am trying to update NSMutableDictionary but I get

mutating method sent to immutable object

error. The itemMutableArray is an instance of NSMutableArray and it contains instances of NSMutableDictionary. Please help.

for(NSMutableDictionary *dict in itemMutableArray){
    for (NSString *key in [dict allKeys]) {
         NSString *kv = [dict valueForKey:key];
         if([kv isEqualToString:[NSString stringWithFormat:@"%@%d",@"FIELD_",k]]) {                                      
             [dict setValue:field.text forKey:@"Value"];
         }
    }
 }

Execption:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010cb07f35 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010c574bb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010cb07e6d +[NSException raise:format:] + 205
    3   CoreFoundation                      0x000000010ca3e8a3 -[__NSCFDictionary setObject:forKey:] + 99
    4   MobileWalletBanking                 0x0000000109e41c62 -[MyViewController validateConnectionFields] + 6178
    5   MobileWalletBanking                 0x0000000109e402f1 -[MyViewController validateInputFields] + 2065
    6   MobileWalletBanking                 0x0000000109e42291 -[MyViewController performBillPayment:] + 97
    7   UIKit                               0x000000010abdb8be -[UIApplication sendAction:to:from:forEvent:] + 75
    8   UIKit                               0x000000010ace2410 -[UIControl _sendActionsForEvents:withEvent:] + 467
    9   UIKit                               0x000000010ace17df -[UIControl touchesEnded:withEvent:] + 522
    10  UIKit                               0x000000010af88540 _UIGestureRecognizerUpdate + 9487
    11  UIKit                               0x000000010ac20ff6 -[UIWindow _sendGesturesForEvent:] + 1041
    12  UIKit                               0x000000010ac21c23 -[UIWindow sendEvent:] + 667
    13  UIKit                               0x000000010abee9b1 -[UIApplication sendEvent:] + 246
    14  UIKit                               0x000000010abfba7d _UIApplicationHandleEventFromQueueEvent + 17370
    15  UIKit                               0x000000010abd7103 _UIApplicationHandleEventQueue + 1961
    16  CoreFoundation                      0x000000010ca3d551 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    17  CoreFoundation                      0x000000010ca3341d __CFRunLoopDoSources0 + 269
    18  CoreFoundation                      0x000000010ca32a54 __CFRunLoopRun + 868
    19  CoreFoundation                      0x000000010ca32486 CFRunLoopRunSpecific + 470
    20  GraphicsServices                    0x000000010e14f9f0 GSEventRunModal + 161
    21  UIKit                               0x000000010abda420 UIApplicationMain + 1282
    22  MobileWalletBanking                 0x0000000109db5733 main + 115
    23  libdyld.dylib                       0x000000010dca4145 start + 1
)
slava
  • 1,901
  • 6
  • 28
  • 32
Tisha Anand
  • 309
  • 5
  • 18
  • 2
    The dictionary isn't a mutabledictionary. Casting it to a NSMutableDictionary variable won't make a standard dictionary mutable. – Paulw11 Nov 17 '15 at 09:16
  • Can you share the code where you add the dictionaries to `itemMutableArray`? – Gordonium Nov 17 '15 at 09:18

3 Answers3

5

Your dictionary clearly is not an instance of NSMutableDictionary, since otherwise you wouldn't get that error.

Rule of debugging: What you think you know is all wrong.

Declaring a pointer as NSMutableDictionary* doesn't make the items mutable dictionaries.

Check your code where you add dictionaries to the array, and check where you are adding immutable dictionaries.

BTW. Read the documentation of valueForKey and setValueForKey. Then read the documentation of objectForKey and setObjectForKey. After reading them, do you really want to use valueForKey? Do you understand that it will sometimes do things that may not at all be what you expect, especially when you have no control over the keys?

gnasher729
  • 51,477
  • 5
  • 75
  • 98
0

As @Paulw rightly said that casting it to a NSMutableDictionary variable won't make a standard dictionary mutable.

Try this:-

NSMutableDictionary *dicNew = [NSMutableDictionary new];

for(NSMutableDictionary *dict in itemMutableArray){
    for (NSString *key in [dict allKeys]) {
        NSString *kv = [dict valueForKey:key];
        if([kv isEqualToString:[NSString stringWithFormat:@"%@%d",@"FIELD_",k]]) {
            [dicNew setValue:field.text forKey:@"Value"];
        }
    }
}
pkc456
  • 8,350
  • 38
  • 53
  • 109
  • valueForKey: is a KVC method. It works with ANY class. valueForKey: allows you to access a property using a string for its name. In this question. tte key is only string, so I used valueForKey. – pkc456 Nov 17 '15 at 09:49
  • OK so you copied some text from the answer to [this](http://stackoverflow.com/questions/1062183/difference-between-objectforkey-and-valueforkey) question. Doesn't sound like you *know* why at all. – trojanfoe Nov 17 '15 at 10:11
  • Yep, I studied the other answers as well and support my answer. Please share the information if I am wrong. – pkc456 Nov 17 '15 at 10:27
  • 1
    `objectForKey:` is an `NSDictionary` method and does the job much more efficiently. `valueForKey:` doesn't provide anything useful in this case. – trojanfoe Nov 17 '15 at 10:29
0

Ok, the problem is your itemMutableArray does not contain mutable Dictionary, i think it will be a normal dictionary.

You have two choices now,

1.just change the normal dictionary to mutable dictionary which is added to itemMutableArray and continue with your code.

2.Use the below code

for(int i = 0; i < itemMutableArray.count; i++)
    {
        NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:[itemMutableArray objectAtIndex:i]];
        for (NSString *key in [dict allKeys]) {
            NSString *kv = [dict valueForKey:key];
            if([kv isEqualToString:[NSString stringWithFormat:@"%@%d",@"FIELD_",k]]) {
[dict removeObjectForKey:@"Value"];
                [dict setObject:field.text forKey:@"Value"];
            }
        }
    }
shlok
  • 113
  • 8