在我的iPhone开发书中,我看到一些奇怪的编码示例,关于当对象添加到数组时以及释放整个数组时数组的作用。一个代码示例在实例数组上具有以下属性:
@property (nonatomic, retain) NSMutableArray* myArray;
作者向数组添加一个对象,然后立即释放指向该对象的指针。阵列单元现在不会指向垃圾数据吗?除非在幕后,阵列单元格在添加时保留对象。
SomeObject* someObject = [[SomeObject alloc] init];
[self.myArray addObject:someObject];
[someObject release];
作者还会释放指向数组的指针,而不首先遍历每个数组单元并释放单个对象。这是内存泄漏,除非在后台发送每个单元格 release 消息;。
- (void)viewDidUnload {
self.myArray = nil;
[super viewDidUnload];
}
答案 0 :(得分:2)
除非在幕后,阵列单元格在添加时保留对象。
是的,这种情况发生了。
......除非在幕后,每个单元格都会发送一条释放消息。
这也会发生。
您已回答了自己的问题。
以下是Collections Programming Topics的引用:
当你添加一个对象时 NSMutableArray对象,该对象 未复制,(除非您将YES传递给 争论的 initWithArray:copyItems :)。相反,一个 object直接添加到数组中。 在托管内存环境中, 对象在收到保留消息时 它被添加;在垃圾收集 环境,它是强烈的 引用。当一个数组是 在托管内存中释放 环境中,每个元素都发送一个 发布消息。
答案 1 :(得分:2)
与C或C ++不同,你经常担心是否删除一个对象,因为担心它仍在其他地方使用,Objective-C(或者说它实际上是Cocoa SDK)使用引用计数机制或者所有权。
您可能已经知道它是如何工作的,但您还需要知道在Cocoa中,如果对象A需要使用另一个对象B,它应该拥有(即保留)它。该对象A不应该依赖于已经保留B的其他对象C,因为它无法知道C何时释放它。因此,在您的情况下,由于NSArray需要在其生命周期中使用添加到其中的所有对象,因此需要保留所有对象。因此,当数组被解除分配时,它需要释放它们。
当你处理大量物品时,这个“你需要保留你想要使用的东西”的概念非常重要。
答案 2 :(得分:1)
苹果开发指南中有几个地方可以解释如果您打算稍后使用它,那么获取对象的所有权(发送保留消息)是一种很好的做法。您应该这样做,以便在您仍然可能需要访问它时不会销毁该对象。
考虑到这一点,你是正确的假设NSArray在将对象添加到集合时会保留该对象,因为它后来仍然可能尝试访问它。
您可以查看“内存管理编程指南”
将对象添加到集合(如数组,字典或集合)时,集合将获得对象的所有权。
或收藏集编程主题了解更多详情
...在托管内存环境中,对象在添加时会收到保留消息。
答案 3 :(得分:1)
第一点你是对的。将对象添加到数组时,该数组将保留该对象。因此,对于之前保留的对象,必须在将其添加到阵列后将其释放,否则最终会导致内存泄漏。
同样,删除对象时 从数组中,数组释放出来 宾语。所以,如果你想保留它, 你需要保留它。
发布数组时,就像你一样 推测,阵列将全部释放 它包含的对象。从而, 单独释放每个对象是 事实上,没有必要 提出异常。
最后,关于代码行 在你引用的-viewDidUnload中:
self.myArray = nil;
只要myArray属性合成如下,这在内存管理方面就可以正常工作:
@synthesize myArray;
Synthesizing创建一个有效执行以下操作的setter:
- (void)setMyArray(NSMutableArray *)anArray
{
if (![myArray isEqual:anArray]) {
[myArray release];
myArray = anArray;
[myArray retain];
}
}
因此,当调用时,上面的setter将首先释放旧数组(只要它与新数组不是同一个对象。)然后,它将保留新数组,在这种情况下为nil。请注意,保留nil将不执行任何操作,并且不会触发错误。
当然,如果你没有合成myArray属性,或者你覆盖了setter,你将会遇到内存问题,除非你还发布了旧的值&将新内容保留在你的二传手中。