【问题标题】:ARC NSMutableArray poolsARC NSMutableArray 池
【发布时间】:2012-11-21 13:35:48
【问题描述】:

我在 NSMutableArray 中保存了一个对象池,因此如果任何其他对象想要引用它们而不是创建新对象,我将简单地给它一个对我已经创建的对象的引用。

过去我会监视对这些对象的保留/释放调用,当它们的保留计数达到 1(仅限我的数组)时,我会将它们从数组中删除。但是,我正在努力使用 ARC 来执行此操作,因为它不允许我监控保留/释放,我将如何执行此操作?

【问题讨论】:

  • 这是一种不好的做法。永远不要依赖retainCount。

标签: ios automatic-ref-counting


【解决方案1】:

创建一种基于释放/保留调用来管理对象的方法,这是很危险的。如果苹果碰巧改变了它的工作方式,那你就完蛋了。显然,当您开始使用 ARC 时,情况就是如此。有两点:

1) 如果对象正在被其他对象使用,您希望将对象独立地保留在NSMutableArray 中。在这种情况下,只需创建对该对象的 __weak 引用,这样您的对象(位于 NSMutableArray 内)就会保持活动状态。

2) 一旦没有对该对象的引用,只需将其从NSMutableArray 中删除。将__weak 对象添加到NSMutableArray。一旦strong 被释放,数组中的那个也会被释放,尽管我不太喜欢这种方法,因为我觉得它很危险。如果您选择此选项,请使用它来存储对象:

NSValue *weakObject = [NSValue valueWithNonretainedObject:anObject];
[array addObject:weakObject];

最后,您只需从该特定文件中删除 ARC,即可继续进行监控。

【讨论】:

  • weaknonretained 之间存在差异。
  • 非保留意味着... retain 未被调用。这与 weak 在释放对象时引用归零的情况非常不同。
  • 来自 Apple 文档:weak 指定与目标对象存在弱(非拥有)关系。如果目标对象被释放,属性值会自动设置为 nil。 (OS X v10.6 和 iOS 4 不支持弱属性;请改用 assign。)
  • 好的。是的,这就是弱引用。但仅仅因为某些东西没有保留并不意味着它很弱,这是我的全部观点。您的帖子暗示使用非保留与使用弱相同,这甚至不接近真实。
【解决方案2】:

我不会为如此复杂的系统而烦恼。只使用强属性和弱属性,不要试图猜测性能。您正在尝试自己构建一个内存管理系统,这对 ARC 来说意义不大。创建和删除对象通常只占任何 Objective-c 应用程序性能的一小部分;经过多年使用 Instruments 监控性能后,我不再担心这部分了。

【讨论】:

    【解决方案3】:

    首先,您应该编写简单的代码,供人类使用。

    在您(通过仪器或其他方法)证明这是一个关键瓶颈之前,不要担心此类性能问题。

    也就是说,创建某些对象可能非常昂贵,因此为某些对象保留缓存本身并不是一个坏主意。但是,您永远不应该依赖引用计数,即使在非 ARC 代码中也是如此。 Apple 文档对此非常清楚。

    正如 Jacky 指出的那样,替代方案是弱引用。不幸的是,您不能将 weak 引用放入标准集合中(不过,具有讽刺意味的是,您可以将它们放入 C++ 集合中并且它们将得到正确管理)。

    但是,您可以创建一个简单的包装类来保存弱引用。

    @interface WeakWrapper : NSObject
    @property (readonly) id object;
    - (id)initWithObject:(id)object;
    @end
    
    @implementation WeakWrapper {
        __weak id _object;
    }
    - (id)object {
        return _object;
    }
    - (id)initWithObject:(id)object {
        if (self = [super init]) {
            _object = object;
        }
        return self;
    }
    @end
    

    然后您可以将这些对象放入集合中,然后...

    WeakWrapper *wrapper = // get the object from the collection
    id object = wrapper.object;
    if (nil == object) {
        // You know the object that was being referenced no longer exists
        // so this wrapper can be removed from the collection and destroyed.
    }
    

    【讨论】:

      猜你喜欢
      • 2012-05-17
      • 2013-02-08
      • 1970-01-01
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多