Why does changing a mutable array contained in a dictionary not require updating the dictionary?

cocoa-touch, collections, objective-c

Solution

That's because in Cocoa, you are using objects and pass by reference.

Imagine this code:

NSMutableArray *a, *b;

a  = [NSMutableArray new];
[a addObject:@"A"]; // a contains @"A"
b = a; // b is assigned to the same object
[b addObject:@"B"]; // a and b contain @"A", @"B"

NSLog(@"a = %p and b = %p", a, b); // same values

The variables `a` and `b` point to the same object. You can also see that by comparing the pointer values.

However, if we do the following:

NSMutableArray *a, *b;

a  = [NSMutableArray new];
[a addObject:@"A"]; // a contains @"A"
b = [[a mutableCopy] autorelease]; // b is assigned to a COPY of the object
[b addObject:@"B"]; // b contains @"A", @"B", while a still contains @"A"

NSLog(@"a = %p and b = %p", a, b); // NOT the same values

`b` is assigned to a copy of `a` (not the original), so `b` points to an other object. You can check by comparing the addresses of the objects.

Problem

I was trying a piece of code from CS193P course (Objective-C). I noticed something in the way that the compiler works. An `NSMutableArray` called `photos` was added to an `NSMutableDictionary`, `photosByPhotographer`. Later on, a change was made to `photos` without any changes to `photosByPhotographer`. When I logged `photosByPhotographer`, the change was automatically applied to it and it did not need any extra lines of code! I wonder how the compiler makes this work? Any materials to read from? The code is as follows: ``` - (void)updatePhotosByPhotographer { NSMutableDictionary *photosByPhotographer = [NSMutableDictionary dictionary]; for (NSDictionary *photo in self.photos) { NSString *photographer = [photo objectForKey:FLICKR_PHOTO_OWNER]; NSMutableArray *photos = [photosByPhotographer objectForKey:photographer]; if (!photos) { photos = [NSMutableArray array]; [photosByPhotographer setObject:photos forKey:photographer]; NSLog(@"photosByPhotographer in if: %@", photosByPhotographer); } [photos addObject:photo]; NSLog(@"photosByPhotographer after if: %@", photosByPhotographer); } self.photosByPhotographer = photosByPhotographer; } ``` The `NSLog()` result is as follows: ``` 2012-07-20 20:05:57.618 Shutterbug[453:f803] photosByPhotographer in if: { Dowbiggin = ( ); } 2012-07-20 20:05:57.620 Shutterbug[453:f803] photosByPhotographer after if: { Dowbiggin = ( { accuracy = 16; context = 0; dateupload = 1342836026; description = { "_content" = ""; }; farm = 9; "geo_is_contact" = 0; "geo_is_family" = 0; "geo_is_friend" = 0; "geo_is_public" = 1; id = 7612787270; isfamily = 0; isfriend = 0; ispublic = 1; latitude = "37.307085"; longitude = "-121.900395"; originalformat = jpg; originalsecret = 052e70d412; owner = "22751315@N05"; ownername = Dowbiggin; "place_id" = cils8sJUV7MeXHwt9A; secret = 4437007c99; server = 8161; tags = "square squareformat iphoneography instagramapp uploaded:by=instagram foursquare:venue=49f13597f964a5209c691fe3"; title = "My little goofball"; woeid = 55971033; } ); } ```

Original source