当NSArray元素被释放时会发生什么?

时间:2011-05-13 16:17:06

标签: objective-c object nsarray null foundation

假设我创建了一些对象,并将它们添加到数组中。

House *myCrib = [House house];
House *johnHome = [House house];
House *lisaHome = [House house];
House *whiteHouse = [House house];

NSArray *houses = [NSArray arrayWithObjects: myCrib, johnHome, lisaHome, whiteHouse, nil];

通常情况下,所有House对象的保留计数为2,但它们会被自动释放一次。过了一会儿,我决定发布myCrib,即使我不是所有者 - 我从未保留或初始化。

[myCrib release];

保留计数应该降为零,我的对象应该被释放。我现在的问题是:这种非法行为是否会导致我的应用程序错误地工作甚至崩溃,或者NSArray只是将我的对象从列表中删除而造成不良后果。

我正在寻找一种维护对象列表的方法,但我希望列表能够维护本身。当某个对象消失时,我希望它的引用能够优雅地自动地从我的数组中消失。我正在考虑子类化或包装NSArray

谢谢。

5 个答案:

答案 0 :(得分:6)

  

我现在的问题是:这是非法的   行动导致我的应用程序工作   错误甚至崩溃,或将会   NSArray只是删除我的对象   它列出了不良后果。

您的数组现在有一个无效的对象指针。只是通过查看它就无法判断指针是无效的,并且不会通知数组该对象已被释放。问题不在于数组,毕竟问题在于代码不正确地释放了对象。所以,是的,由于错误的指针,应用程序可能会崩溃或行为不正确,并且不会,NSArray不会检测到并为您处理问题。

  

我正在寻找一种方法来维持一个   对象列表,但我想要列表   保持自己。当一些对象   消失了,我想要它的引用   从我的阵列中优雅地消失   并自动。

如果列表中的对象都是公共类的实例,则可以定义自己的内存管理方法,这些方法既保留/释放对象,又从列表中添加/删除对象,或者在可能的情况下广播适当的通知多个清单。我想你甚至可以为这个目的覆盖-retain和-release,但是在做这件事之前我会考虑很久很难,如果你做的话就记录好了;这不是其他开发人员所期望的那种。

另一种选择可能是核心数据。如果从对象图中删除托管对象,它将从任何关系中消失。严格地说,多对多关系是一个集合,而不是列表,但差异可能不是您的目的。

更新:我刚刚注意到您没有标记问题ios。如果你在MacOS X下工作,你一定要看看NSPointerArray。如果使用垃圾收集,则可以将NSPointerArray配置为使用弱引用并使用空引用替换对收集的对象的引用。这正是您正在寻找的。

答案 1 :(得分:3)

  

我正在寻找一种方法来维持一个   对象列表,但我想要列表   保持自己。当一些对象   消失了,我想要它的引用   从我的阵列中优雅地消失   并自动。我在想   子类化或包装NSArray。

如果我理解正确,你想要的是一系列弱引用。然后,您可能有兴趣阅读this post

答案 2 :(得分:2)

如果您不是所有者,则应发布myCrib。这样做违反了内存管理准则,并且会使您的代码难以维护。我无法强调你在任何情况下绝对不应该这样做。你要求崩溃;数组声明了对象的所有权,并且不得以任何方式破坏该所有权。

所以答案就是:你的代码绝对错误,你应该修复它。如果你无法修复它,你应该删除它并重新开始并继续重写它,直到你想出另一种方法来实现相同的效果而不破坏对象的所有权。我保证这是可能的。


如果您想要的是一个弱引用数组,那么有几种方法可以做到这一点(这个was just asked a couple of days ago):

  1. NSPointerArray - 弱引用其指针。当您使用垃圾收集时,它们会自动清零(即,在取消分配对象时,指针会被删除)。不幸的是,这在iOS上不可用。
  2. CFMutableArrayRef - 您可以指定自定义retainrelease回调,或者根本不指定回调。如果将它们遗漏,数组将不会保留它包含的对象。但是,在取消分配对象时,这不会自动删除指针。
  3. DDAutozeroingArray - 我前几天编写的NSMutableArray子类,提供了一个适用于Mac OS和iOS的弱引用和自动归零数组。但是,我强烈鼓励您仅将此作为最后手段使用;做你正在寻找的东西可能有更好的方法。 https://github.com/davedelong/Demos

答案 3 :(得分:1)

你在这里要求崩溃。你的NSArray仍然会引用现在不再存在的对象 - 谁知道它会在一段时间后指向什么?

子类化NSArray可能也不是答案。它是一个类集群,简而言之,意味着它比你希望的更难分类。

不完全确定你是如何实现这一点的。类似于元素在它们即将被释放时发送通知的元素然后拾取的元素。您需要小心不要泄漏或过度释放物体。

答案 4 :(得分:0)

我创建了一个包装类 - 在我的代码中它被称为控制器 - 它为我维护(可变)数组。我在视图控制器中初始化控制器类 - 我需要它们的地方 - 而不是直接使用数组。

对我来说没有无效代码。 :-P