我必须保留 NSMutableArray 尽管它是一个属性
我是新手,但我阅读了很多有关内存管理的内容,并且确实尝试自己找到答案。 这听起来很基本,但我显然不明白。 我在 .h 中有一个 NSMutableArray 作为属性:
@property (nonatomic, retain) NSMutableArray *documentListArray;
我合成它并在 (void) dealloc 中释放它。 为了填充数组,我有一个方法 - (void)updateRecordList ,其中:
self.documentListArray=[DocumentDatabase getDocumentListSortedByDate];
编辑:下一行:
[[self recordListTableView] reloadData];
其中 DocumentDatabase 是一个不同的类,具有类方法 getDocumentListSortedByDate 和 getDocumentList。 中发生的情况,
NSMutableArray *returnArray = [DocumentDatabase getDocumentList];
//sorting...
NSLog("array count:%i",[returnArray count]); //returns correct numbers first and second time
return returnArray;
这是 getDocumentListSortedByDate:和 getDocumentList
NSMutableArray *returnArray = [NSMutableArray arrayWithCapacity:files.count];
//add file data to array...
return returnArray;
这在我第一次调用 updateRecordList 时有效,但在添加文件并第二次调用 updateRecordList 后,它崩溃了(使用 NSZombies): * -[NSCFNumber dealloc]:发送到已释放实例 0x7504c90 的消息。 通过大量日志记录,我将问题范围缩小到 updateRecordList 中上面的行,如果我将其更改为:
self.documentListArray=[[DocumentDatabase getDocumentListSortedByDate] retain];
我的结论是 getDocumentList 中的数组在到达之前已自动释放。所以我的问题是:
1. 为什么我必须将其保留在那里?难道不应该通过声明属性(保留)来自行发生吗? 或者,换句话说,为什么数组自动释放得太早(假设这就是正在发生的情况)?
2.当我给self.documentListArray分配一个新数组时,旧数组是否会自动释放?如果我尝试在获取新文档列表之前自己释放它,它也会崩溃。
预先感谢您的回复。
编辑: 也许我是个白痴:我没有提到 documentListArray 是 UITableView 的数据源(请参阅顶部添加的行)。我怀疑我在填充表视图时做错了什么,并且数组被保留......?但是,它会在分配属性时崩溃,而不是在 reloadData 时崩溃。 我回去研究一下我是否正确使用了UITableViewDataSource协议。感谢大家,你们的回答让我希望走上正轨。解决后会更新。
编辑2: 现在它可以在没有保留的情况下工作,我想我明白为什么:我进行了广泛的调试,发现添加到数组中的对象中包含的对象为零。特别是,在encodeWithCoder的深处,我在分配值时没有使用“self”。解码时,这些值为零。自从我改变了这一点后,它似乎起作用了。 我怀疑不是分配新数组导致了崩溃,而是 TableView 会读取新数组 - 甚至在我调用 reloadData 之前。这又回到了 David 的同步访问问题。谢谢大家的帮助。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您显示的代码看起来是正确的;只要您在自动释放池耗尽之前将值分配给具有
retain
语义的属性,就没有必要(或正确)自己调用保留。所有调用(getDocumentListSortedByDate、getDocumentList)是否同步发生,或者您是否在后台执行这些操作?仔细检查您是否使用“self”进行分配。 ("self.documentListArray=") 而不是直接分配给实例 var("documentListArray=");如果您省略“self”,则会绕过设置器。不,在分配之前不要释放旧值;这是setter 的工作。
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.