3

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

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

谢谢你。

4

5 回答 5

6

我现在的问题是:这种非法行为会导致我的应用程序错误地工作甚至崩溃,还是 NSArray 会简单地从其列表中删除我的对象而产生不良后果。

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

我正在寻找一种方法来维护对象列表,但我希望列表能够自行维护。当某个对象消失时,我希望对它的引用从我的数组中优雅而自动地消失。

如果列表中的对象都是公共类的实例,您可以定义自己的内存管理方法,既保留/释放对象,又从列表中添加/删除它,或者在可能有多个列表的情况下广播适当的通知。我想你甚至可以为此覆盖 -retain 和 -release ,但我会在这样做之前仔细考虑一下,如果你这样做的话,请做好记录;这不是其他开发人员所期望的。

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

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

于 2011-05-13T16:22:45.377 回答
3

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

如果我理解正确,您想要的是一组弱引用。那么,您可能有兴趣阅读这篇文章

于 2011-05-13T16:52:46.633 回答
3

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

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


如果你想要的是一个弱引用数组,那么有几种方法可以做到这一点(这只是在几天前被问到):

  1. NSPointerArray- 弱引用它的指针。当您使用垃圾收集时,它们会自动归零(即,当对象被释放时指针会被删除)。不幸的是,这在 iOS 上不可用。
  2. CFMutableArrayRef- 您可以指定一个自定义retainrelease回调,或者根本不指定一个。如果将它们排除在外,则数组将根本不会保留它包含的对象。但是,这不会在对象被释放时自动删除指针。
  3. DDAutozeroingArray-NSMutableArray我前几天写的一个子类,用于提供一个弱引用和自动归零数组,适用于 Mac OS 和 iOS。但是,我强烈建议您仅将其用作最后的手段;可能有更好的方法来做你正在寻找的事情。 https://github.com/davedelong/Demos
于 2011-05-13T16:42:38.760 回答
1

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

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

不完全确定您将如何实现这一点。类似于元素在即将被释放时发送通知,然后数组将拾取该通知。您需要小心不要泄漏或过度释放您的对象。

于 2011-05-13T16:30:34.347 回答
0

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

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

于 2011-05-14T10:32:42.883 回答