释放 NSArray 时将对象设置为 nil

Posted

技术标签:

【中文标题】释放 NSArray 时将对象设置为 nil【英文标题】:setting objects to nil when releasing NSArray 【发布时间】:2009-08-18 10:59:10 【问题描述】:

当我收到内存警告时,我正在释放存储在 NSMutableArray 中的一堆对象。

[_children release];

我还需要在某个时候递归遍历对象(可能在发生内存警告之后),所以我需要检查对象是否仍然存在,我通过与 nil 进行比较来执行此操作 - 这是行不通的因为释放数组并没有任何东西。

我无法遍历数组,逐一删除对象并将其设置为 nil,因为我不允许在迭代期间修改数组。

感觉好像我错过了一些明显的东西。我只想释放 + nil 数组中的一些值。

【问题讨论】:

【参考方案1】:

对不起,但你所做的对我来说似乎毫无意义。不能将对象设置为 nil,只能将对象的引用设置为 nil,但这会影响其他引用。

NSObject * a = [[NSObject alloc] init];
NSObject * b = a;

[a release];
a = nil;

// b is NOT nil! b still points to the memory location where
// a used to be, which is now not valid anymore and using b
// for anything may crash your application!

如果我将“a”放入数组中,然后再次从数组中删除,“a”的保留计数会减一。要么它仍然大于零,在这种情况下“a”将不被释放,要么它为零,在这种情况下它被释放。在 a 被释放后将其引用设置为 nil 对仍然指向“a”的其他变量没有影响。

因此,即使 NSArray 在将“a”的引用删除到数组并释放它之后将其设置为 nil(因为它的引用计数为零),它也不会影响仍然指向“a”的实例变量.

我不太确定你想做什么,这当然是可能的,但你在这里完全错了。

【讨论】:

感谢您的澄清。我在错误的轨道上并找到了解决方法。我来自 C++ 背景,所以这不是很明显。在您的示例中,我会假设 b == nil 由于我不知道您真正在做什么,因此我无法提出更好的解决方案。如果数组中的对象是您自己的类,您当然可以覆盖 dealloc 方法(当保留计数达到零时调用该方法)并通知其他对象(例如委托或只是广播通知)您现在将死,所以所有其他对象可以将它们对您的引用更新为 nil。 即使在 C++ 中,如果你有一个指向对象的指针,当对象本身被销毁时,你持有的地址不会被清除 - 你会有一个无效的指针,就像 Objective-C保留计数下降到 0 并且您仍然有一个指向用于分配内存的位置的引用...【参考方案2】:

假设您没有在其他地方保留数组元素,肯定是通过从数组中删除一个对象,或者释放数组本身,您也释放了元素。我认为这就是你需要做的。

来自 Apple 文档:

每个对象都会收到一条保留消息 在将其 id 添加到数组之前 以及发布消息 从数组中删除或当 数组被释放

【讨论】:

但是我怎么知道它已经发布了呢?我无法查询它,因为它不存在,它给我留下了一个悬空指针...... 因为 Apple API 是这么说的。它说如果你从数组中删除一个对象,或者释放数组 - 数组对象将被释放。 你误会了——如果 (appleAPISaysThisObjectIsReleasedOrNot()) 在运行时我不能这样做。我找到了一个解决方法,所以还是谢谢。

以上是关于释放 NSArray 时将对象设置为 nil的主要内容,如果未能解决你的问题,请参考以下文章

自动释放的 NSArray 会导致内存泄漏吗?

安全的 NSArray 访问

Objective-c:从方法返回自动释放的对象

释放Object时viewDidUnload和dealloc函数之间的区别

在两个视图控制器之间转换时将 NSArray 存储到文件

java在创建文件对象时将文件权限设置为777 [重复]