超越NARC:何时保留,何时分配,何时复制

时间:2010-07-18 21:06:49

标签: objective-c memory-management narc

我终于明白我是否必须释放一个对象,以及如何在一个简单的应用程序中保持我的保留计数尽可能低(通过知道该对象是否带有额外的'retain'已经调用过来)。所以NARC的规则在这方面做得很好。

另一方面,我无法围绕是retain(通常使用保留属性)还是assign实例变量。那里有经验法则吗?我只知道两个:

  1. 如果我在我的班级中创建了实例(例如,在init中),那么我应该保留它并在dealloc中释放它。
  2. 代表获得分配,而不是保留
  3. 但我不明白的是我是否应该保留我从另一个实例传递的东西。我知道风险是保留计数降到零并且我留下了包(或者留下了许多额外的包和内存),但是......我应该如何组织我的应用程序以便不会发生这种情况?

    我见过一些related questions,但没什么一般的。

    我在这里的时候:已经添加到UIWindowUIView但我未亲自保留的内容呢?如果他们的超级视图从所有超级视图中删除,“自然”保留的实例是否会被取消分配?

2 个答案:

答案 0 :(得分:10)

对于您想要的类型对象:

  • retain默认
  • copy如果该类来自可变/不可变类集群
  • assign如果您需要weak references

至于清理,所有retaincopy属性都必须为released

  

如果我在我的类中创建了实例(例如,在init中),那么我应该保留它并在dealloc中释放它。

问题不在于它是否是在你班级的方法中创建的,而是你是否:

  • 想要强烈引用实例
  • 已经拥有它

如果您还没有拥有它并希望强烈引用它,请保留 - 对于传递给您的方法的实例也是如此。无论是通过setter明确地还是隐式地保留都无关紧要。

答案 1 :(得分:2)

  

如何保持我的保留计数尽可能低

我不明白这一点。是什么让你认为你需要担心保留计数?保留计数是一个实现细节,忘了它。您需要担心的是您是否拥有一个对象。

  

我无法解决是否保留(通常使用保留属性)或只是分配实例变量。

在几乎所有情况下,您都希望在分配实例变量时保留或复制。主要的例外是保留周期。有时,您发现自己处于这样的情况:对象A具有对对象B的引用,对象B具有对对象A的引用。如果A保留B和B保留A,则不能依赖于在dealloc中释放引用的正常模式他们走开了。在这种情况下,通常指定一个对象作为所有者,另一个对象作为所有者。拥有的对象将不会保留其对所有者的引用。

这样的示例是树结构,其中父节点具有对其子节点的引用,并且每个子节点都具有对其父节点的引用。如果每个孩子保留其父母,当申请与父母一起完成时,它将不会消失,因为它已被所有孩子保留。因此,父引用被实现为弱引用,这意味着子引用不保留其父引用。

这是一个非常常见的模式,代理的所有者将自己设置为对象的委托。例如,表视图的控制器通常也是表视图的数据源和/或委托。如果表视图保留了委托,则会有一个保留周期(因为控制器已经保留了视图)。这就是为什么会议“代表们不被保留”的原因。

如果您想要引用的对象实现NSCopying,并且您需要在拥有所有权时不需要更改,则应该复制。 Cocoa的一个例子是NSDictionary中元素的键。如果要在字典中更改密钥,那将是一场灾难。所以NSDictionary复制了它的密钥。

  

我知道存在的风险是保留计数降到零并且我留下了包(或者留下了许多额外的行李和内存),但是......我应该如何组织我的应用程序以便这样做呢?发生了吗?

简单:按照Cocoa memory management rules。如果你拿着它的东西就会消失,你就没有那个东西了。如果您需要的东西要比当前方法的范围更长,那么您应该保留它。