I'm new, but I read a lot about memory management, and really tried to find the answer myself. It sounds so basic and yet I apparently don't get it. I have a NSMutableArray as property in .h:
@property (nonatomic, retain) NSMutableArray *documentListArray;
I synthesize it and release it in (void) dealloc. To populate the array, I have a method - (void)updateRecordList and in there:
self.documentListArray=[DocumentDatabase getDocumentListSortedByDate];
EDIT:next line:
[[self recordListTableView] reloadData];
where DocumentDatabase is a different class with the class methods getDocumentListSortedByDate and getDocumentList. Here is what is happening in getDocumentListSortedByDate:
NSMutableArray *returnArray = [DocumentDatabase getDocumentList];
//sorting...
NSLog("array count:%i",[returnArray count]); //returns correct numbers first and second time
return returnArray;
and in getDocumentList
NSMutableArray *returnArray = [NSMutableArray arrayWithCapacity:files.count];
//add file data to array...
return returnArray;
This works the first time I call updateRecordList, but after adding a file and calling updateRecordList a second time, it crashes with (using NSZombies): * -[NSCFNumber dealloc]: message sent to deallocated instance 0x7504c90. With a lot of logging I narrowed the problem down to the line above in updateRecordList and it works if I change it to:
self.documentListArray=[[DocumentDatabase getDocumentListSortedByDate] retain];
My conclusion is that the array down in getDocumentList has been autoreleased before it arrives. So my questions are:
1. Why do I have to retain it there? Shouldn't that happen by itself by declaring the property (retain)?
Or, in other words, why is the array autoreleased too early (assuming this is what is happening)?
2. When I assign a new array to self.documentListArray, is the old array automatically released? If I try to release it myself before getting a new documentList, it crashes too.
Thanks in advance for any reply.
EDIT: Maybe I'm an idiot: I failed to mention that documentListArray is the data source for an UITableView (see the added line on top). I suspect that I am doing something wrong with populating the table view, and the array gets retained...? It does however crash on assigning the property, not on reloadData. I go back to study if I use the UITableViewDataSource protocol properly. Thanks to everybody, your answers brought me hopefully on the right track. Will update when solved.
EDIT2: It works now without retaining, and I think I understand why: I debugged extensively and found that Objects contained in Objects added to the array where nil. Particularly, deep down in encodeWithCoder I did not use "self" when assigning values. When decoding, those values where nil. Since I changed that, it seems to work. I suspect that not assigning the new array caused the crash, but the TableView which would read the new array-even before I call reloadData. Which would lead back to Davids question of synchroneous access. Thank you all for your help.
The code you've shown it appears correct; it should not be necessary (or correct) to call retain yourself, as long as you are assigning the value to a property with retain
semantics before the autorelease pool is drained. Are all the calls (getDocumentListSortedByDate, getDocumentList) happening synchronously, or are you doing any of this in the background? Double-check that you're assigning using the "self." ("self.documentListArray =") instead of just assigning directly to the instance var ("documentListArray ="); if you omit the "self.", the setter is bypassed.
No, don't free the old value before assigning; that's the setter's job.