I have declared an NSMutableArray *arrAllRecordsM
and am trying to add NSMutableDictionary *dicRecordM
to it using addObject
. The dicRecordM
gets added to arrAllRecordsM
but on doing [dicRecordM removeAllObjects]
it sets to nil in arrAllRecordsM
. Below is the code, please help me fix it.
self.arrAllRecordsM = [NSMutableArray array];
self.dicRecordM = [NSMutableDictionary dictionary];
// Some Method
[self.dicRecordM setObject:@"Test" forKey:@"ADDRESS"];
[self.arrAllRecordsM addObject:self.dicRecordM];
// Value: Test
NSLog(@"Value: %@", [[self.arrAllRecordsM objectAtIndex:0] valueForKey:@"ADDRESS"]);
[self.dicRecordM removeAllObjects];
// Value: null
NSLog(@"Value: %@", [[self.arrAllRecordsM objectAtIndex:0] valueForKey:@"ADDRESS"]);
Adding an object to an NSMutableArray
just stores a pointer (or "strong reference")
to the object into the array. Therefore
[self.arrAllRecordsM objectAtIndex:0]
and
self.dicRecordM
are two pointers to the same object. If your remove all key/value pairs from self.dicRecordM
then [self.arrAllRecordsM objectAtIndex:0]
still points to the same
(now empty) dictionary. That is the reason why
[[self.arrAllRecordsM objectAtIndex:0] valueForKey:@"ADDRESS"]
returns nil
.
If you want an independent copy of the dictionary in the array, use
[self.arrAllRecordsM addObject:[self.dicRecordM copy]];
copy
can be used on many classes, such as NSDictionary
, NSArray
and NSString
and their mutable variants, to get a "functionally independent object". Formally, it is available for all classes conforming to the NSCopying
protocol.
This is expected behavior.
You removed all the objects from the dictionary by calling removeAllObjects
, then tried to retrieve an object from it and rightfully getting nil
, since it doesn't exist in the dictionay anymore (you removed it).
What's maybe unclear to you is that NSArray
doesn't copy the element you add to it, instead it just holds a strong reference.
So both dicRecordM
and arrAllRecordsM
are holding a reference to the same object, hence any modification to it (in this case removeAllObjects
) will affect the same dictionary.
Incidentally, you shouldn't use valueForKey:
for accessing the dictionary's entries. Use objectForKey:
or the shorter subscripted syntax. For instance
self.arrAllRecordsM[0][@"ADDRESS"]
You can read this answer Difference between objectForKey and valueForKey? as a reference, but the main problem is that valueForKey:
can behave very differently from objectForKey:
in case the key contains special KVC characters, such as @
or .
.