【问题标题】:What happens when an NSArray element gets deallocated?当一个 NSArray 元素被释放时会发生什么?
【发布时间】:2011-08-25 02:06:30
【问题描述】:

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

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

谢谢。

【问题讨论】:

    标签: objective-c object nsarray null foundation


    【解决方案1】:

    我现在的问题是:这是否违法 行动导致我的应用程序工作 错误地甚至崩溃,或者将 NSArray 只需从中删除我的对象 后果很严重。

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 但是当数组有对它的引用时,一个对象不会被释放。
      • @Caleb 我的理解是他想要release 对象 for 数组,从而迫使它被释放。
      • @Dave,我认为它是:“我希望数组跟踪一组对象,但前提是它们有效。”他想避免不得不维护阵列。你是对的,正如所写的那样,他试图释放数组的对象,这显然是错误的。但是目标是有效的,正如我在更新的答案中所写,我 认为 NSPointerArray 如果在他的环境中可用,就会做他想做的事。
      • @Caleb 公平点;我用我前几天写的一些代码的链接更新了我的答案。
      【解决方案3】:

      如果您不是所有者,您应该释放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

      【讨论】:

      • 我知道这是无效代码,这就是为什么我说如果我实际使用这个无效代码会发生什么。反正我找到了更好的方法。 :-)
      【解决方案4】:

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

      如果我没有理解错,你想要的是一组弱引用。那么,您可能有兴趣阅读this post

      【讨论】:

      • +1 将我击败到 NSPointerArray。这是一个非常好的线程。
      • +1 从未听说过NSPointerArray。必须在某个时候进行一些 Mac 编程...
      【解决方案5】:

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

      我没有无效代码。 :-p

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-17
        • 1970-01-01
        • 2016-01-15
        • 2017-03-24
        • 2023-03-25
        • 2011-05-20
        • 2013-03-11
        • 2011-11-27
        相关资源
        最近更新 更多