1

based on the fact that you cannot edit mutable Collections while enumerating them, this is the best solution i could come up with to edit a Array of NSMutableDictionaries:

__block NSMutableDictionary *tempDict = [NSMutableDictionary dictionaryWithCapacity:1];
__block NSUInteger idx;
[_myArray enumerateObjectsUsingBlock:^(NSMutableDictionary* obj, 
                                                        NSUInteger indx, BOOL *stop) {
    if (// some condition is met) {
        tempDict = [obj mutableCopy];
        idx = indx;
    }
}];

[tempDict setObject:[NSNumber numberWithInt:thisQueryResults] forKey:@"resultsNum"];
[_myArray replaceObjectAtIndex:idx withObject:rowSelected];

this seems way too complicated (even for a language like obj-c).. and since it's involving two data types (NSMutableArray and NSMutableDictionary), it doesn't seem like I can cleanly put them into a category.. advice?

update: one comment asked why do I create a mutablecopy (as opposed to just a copy.. since it's copying a mutable object)..

suppose I just used copy.. if i put a break on tempDict this is what I get:

// tempDict = [obj copy]
po tempDict
$0 = 0x0b28cc10 <__NSArrayI 0xb28cc10>(
1
)

// tempDict = [obj mutableCopy]
po tempDict
$0 = 0x0b28cc10 <__NSArrayM 0xb28cc10>( //notice the M in __NSArrayM as opposed to I above
1
)

in case of copy.. if I follow it with a line like this: [tempDict setObject:[NSNumber numberWithInt:thisQueryResults] forKey:@"resultsNum"];

I get this error:

[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0xb245100

I get the same above error with this code:

for (NSUInteger idx = 0; idx < [_myMutableArray count]; idx++) {
    NSMutableDictionary* myMutableDict = _myMutableArray[idx];
    [myMutableDict setObject:obj forKey:key];        
}

update 2: the origin of the problem was instantiating non mutable arrays and dictionaries.. I'm new to the whole new obj-c literals, so I didn't know that to create a NSMutableArray and NSDictionary, you gotta do this, respectively:

[@[..] mutableCopy]
[@{..} mutableCopy]
Community
  • 1
  • 1
abbood
  • 23,101
  • 16
  • 132
  • 246

3 Answers3

1

So in your case, I don't quite follow why you call tempDict = [obj mutableCopy]; when from the conditions you write the dictionary is already writable.

You can use several tricks. Like using

for (NSUInteger idx = 0; idx < _myArray.count: idx++_ {
   NSMutableDictionary *obj = _myArray[idx];

  // modify
}

For NSDictionaries you can get allKeys and iterate over that copy. This is a bit slower than using fast enumeration, but still faster than doing workarounds like boxing integers to replace later :)

BenMorel
  • 34,448
  • 50
  • 182
  • 322
steipete
  • 7,581
  • 5
  • 47
  • 81
  • i'm afraid it doesn't work.. this is what i tried:` for (NSUInteger idx = 0; idx < [_rowsSelectedInfo count]; idx++) { NSMutableDictionary* rowSelected = _rowsSelectedInfo[idx]; [rowSelected setObject:[NSNumber numberWithInt:thisQueryResults] forKey:@"resultsNum"]; }` I get this error: `-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0xb245100` for some reason it's casting the NSMutableDictioanry to __NSDictionaryI.. it's the same error I got before I resorted to my ugly solution – abbood May 10 '13 at 12:29
  • Then you need to check your array - NSArray only retains and not copies objects, so somewhere in your code you're adding non-mutable data structures. But you can always add a mutableCopy - when the NSDictionary is already mutable, this does simply retain the object. – steipete May 10 '13 at 12:45
1

In your case you are NOT modifying the array at all only the dictionaries within the array. There are no contstraits on how you modify the objects within the array. Here is a bit of equivalent code:

for (NSMutableDictionary *dict in _myArray) {
    if (someCondition)
         [dict setObject:[NSNumber numberWithInt:thisQueryResults] forKey:@"resultsNum"]
}

You would have a problem if you absolutely needed to replace the object in your array. In that case, if the array is not huge I would suggest the same as @Markus. Iterate over a copy and modify the original.

aLevelOfIndirection
  • 3,522
  • 14
  • 18
  • The reason you get this error is that although you thing that you have mutable dictionaries in your array they in fact are not. Look at the point in your code where you originally create this array and add dictionaries to them and ensure that they are mutable dictionaries. Hint: `@{}` will create a NSDictionary not a NSMutableDictionary. You could do `[@{} mutableCopy]` though. – aLevelOfIndirection May 10 '13 at 14:41
0

Maybe you can use KVC and do :

NSArray<NSMutableDictionary *> *result = [[_myArray filteredArrayUsingPredicate:[NSPredicate withFormat:@"{YOUR CONDITION}"]] valueForKey:@"mutableCopy"];
iPav
  • 101
  • 1
  • 7