【问题标题】:automatic reference counting (ARC) and retainCount自动引用计数 (ARC) 和 retainCount
【发布时间】:2012-03-21 04:48:31
【问题描述】:

我正在将我的项目转换为使用 ARC,但遇到了一个特殊问题。我有一个类管理从网络下载的文件的缓存。每个文件都存储在 iPhone 文件系统中,并在我的管理器类中为它保存一个关联的对象。 其他想要使用文件的对象,向我的经理请求缓存对象,并在需要该文件时保留该对象。

但有时,管理器会清理缓存,删除旧文件。当然,它不应该删除当时正在使用的文件。在 ARC 之前,我通过使用关联对象的 retainCount 检测到:

// if retainCount is 1 then only the cache has a reference to it
if( obj.retainCount <= 1 ) {
    [obj deleteFile];
    [cache removeObject:obj];
}

效果很好 [是的,我知道有关 retainCount 不可靠性的警告,但根据我的经验,如果 retainCount > 1,你肯定知道不止一个对象保留了它]

但是,对于 ARC,您不能再使用 retainCount。我可以引入我自己的保留计数机制,并要求所有使用文件的对象显式保留和释放文件对象。但这很容易出错,而这正是 ARC 应该解决的问题。

您知道实现相同目标的更好方法吗?

【问题讨论】:

标签: objective-c cocoa-touch ios5 automatic-ref-counting retaincount


【解决方案1】:

此功能最好由NSCacheNSDiscardableContent 处理。这使用了显式的startend 调用,这允许您维护对您不一定需要保留的事物的强引用(因为您将自动重新创建它们)。为此使用NSCache 还可以为您带来其他优势,例如即使您被暂停,也会自动转储可丢弃的内容。如果没有像NSCache 这样的东西,当内存不足时你会被杀死,而不是让你转储多余的缓存。

也就是说,您已经构建了另一个系统。这个特殊的问题是 weak 引用的目的。您的缓存应该保持对对象的弱引用而不是强引用。 Non-retaining array for delegates 中讨论了几种方法。我个人更喜欢NSValue 解决方案。批准的答案听起来很棒而且很简单,但是您需要很好地理解 ARC 和 CFArray 才能正确使用它。 NSValue 解决方案要简单得多。

理想情况下,如果您的文件对象知道它们已被缓存,它们可以告诉缓存在它们的dealloc 期间删除它们。否则,您可以定期从数组中清除空值。

【讨论】:

  • NSCache 是一个很好的技巧,我不知道。我一定会研究我是否可以使用它。我最初认为我不能使用的弱引用:这意味着我的对象和相关文件将在不再使用时被删除。我有一个缓存来避免这种情况。但是考虑一下:我可以让文件对象被弱引用清理,但保留文件。然后清理代码可以检查哪些引用是零,并删除相关文件。嗯,可能有用。谢谢!
  • 我查看了 NSCache,坦率地说,它看起来并不是很有用。尽管它说它“包含各种自动删除策略”,但似乎没有办法设置要使用的策略。例如,如果您知道如何设置 LRU(或 LFU)移除策略,请告诉我。快速的互联网搜索没有找到有用的答案。
【解决方案2】:

只需在对象的实现中设置一些 int 变量,每次保留对象时递增它并覆盖其 dealloc 方法以递减它。相同的保留计数,但仅适用于自定义对象。

【讨论】:

  • 好吧,我的文件对象的dealloc不会被调用,因为我的缓存里还有对它的引用。还是您的意思是使用文件对象的所有不同对象的释放?这和设置我自己的引用计数系统一样,不是吗?
  • 他可能打算在发布时减少它,而不是 dealloc。我不确定这是否可行,因为我相信 ARC 绕过了正常的保留和释放方法,甚至可能不允许您覆盖它们。
  • @UIAdam,在ARC下,调用retain或release完全是错误的。
  • @RobNapier 当然,我知道很多都是真的,但我有点不确定 ARC 是否会自己调用一个类的“真实”保留/释放方法,或者它是否使用不同的东西(我很确定是这样)。
  • 是的,它使用了多种 objc_* 函数调用,并且在某些情况下甚至优化了这些。在任何情况下,它都不会调用您覆盖的 -retain 或 -release。
【解决方案3】:

不确定这是否可以满足您的需求,但您知道Associative References 吗?这些允许您将从属对象附加到主对象,以便从属对象与主对象一样存在。这不仅允许将对象附加到您无法控制的对象上,而且您还可以了解它们的使用寿命。

我想知道您是否可以通过将自定义类对象附加到它来使用它来监视您的“obj”,并且如果“obj”被释放,则将调用该自定义类的 dealloc。然后,您可以在该自定义 dealloc 中执行文件删除。

【讨论】:

  • 我不知道关联引用,它们非常令人印象深刻,尤其是与类别一起使用。谢谢你的提示!但是,在这种情况下,它们不适用,因为我可以控制原始对象。无论我在关联对象中做什么,我都可以在原始对象(的释放)中执行。而且我已经在原始对象中实现了显式引用计数,因此问题不再是当前问题。
猜你喜欢
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
  • 1970-01-01
  • 2015-09-29
  • 2012-02-21
相关资源
最近更新 更多