views:

119

answers:

2

I have a general question about objects, memory, and retaining.

I am not a complete newb (I have apps for sale on the iTunes Store) but something must have slipped past me. I work with the Google Docs API, and yesterday I was downloading a spreadsheet feed, and enumerating the results, namely, the Spreadsheet Record Feed.

After enumerating and adding objects to a dictionary, the dictionary got added to an array before the loop went to the next Record. So after 5 times through, the array had 5 objects, one dictionary per record, with values from each. Weirdly, at the end, the Array had 5 copies of the same information. Each time through the loop, the dictionary changed, like it was supposed to, but when I inserted it into the array, the other objects in the array changed to match.

I looked through some stuff on StackOverflow and found a suggestion to try this:

[array insertObject:[dictionary copy] atIndex:0];

That fixed it. Adding the copy method made everything work like normal.

I'm just wondering why.

+3  A: 

Usually, when an object is put into an array, it's kept intact even if the original object is modified or destroyed.

You are mistaken. Arrays (and all other container classes in Cocoa) never work like that. They only store a reference to the objects they contain (and retain them) so any changes in the original objects will be reflected if you retrieve them from the array (because they are the same objects).

Sure, by calling copy you are creating a copy of the dictionary so now you are dealing with separate objects. At the same time, you are now leaking memory because you are responsible for releasing an object that is returned from copy.

Also, bear in mind that copy only makes a shallow copy, so the actual content of the copied dictionaries is not being copied. If you change the dictionaries' contents, these changes will be reflected in both dictionaries (the "original" one and the copied one you have added to the array).

Ole Begemann
Thanks for your reply. I took the part you quoted out so I don't look like such a moron (and so no one else is confused).What is the best practice for adding NSDictionary objects to NSArrays in a loop?
JustinXXVII
The best practice is to avoid having mutating objects in a collection, and if you must do it, treat them like they're radioactive.
Chuck
+2  A: 
e.James
Thank you! What is the best practice to insert NSDictionary objects to NSArray objects in a loop? Should I be alloc-init-ing a new dictionary at the start and releasing at the end of each loop?I took out the part at the end so as not to confuse anyone else. Also, so I don't look like such a tool
JustinXXVII
Yes, that is a better way to do it. Autorelease is not recommended for iPhone apps, especially in loops. I modified my answer and added a link to some supporting information. Full disclosure: the linked question is mine :)
e.James