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.
When you insert an object (let’s call it X) into an array, what actually gets placed into the array is a copy of the pointer to X, and not a copy of X itself. X is sent a
retainmessage so that the array can hold on to it, but X is not sent acopymessage. This means that changes to X later on will affect the object “stored” in the array.WARNING: The suggested solution results in a substantial memory leak, since the copied data is never released. A better solution is to autorelease the copied array, so that it will be released when the array is released.
Or, for iPhone code (in which autorelease can be bad, especially in loops):
UPDATE: Be sure to read Ole Begemann’s answer as well. He makes an excellent point about deep vs. shallow copies of the dictionary.