超越 NARC:何时保留、何时分配、何时复制
我终于明白是否必须释放一个对象,以及如何在一个简单的应用程序中将保留计数保持在尽可能低的水平(通过知道该对象返回时是否带有已调用的额外“保留”)。因此,NARC 规则在这方面运作良好。
另一方面,我无法确定是否要保留
(通常使用保留属性)或只是分配
实例变量。有什么经验法则吗?我只知道两个:
- 如果我在我的类中创建了实例(例如,在 init 中),那么我应该保留它并在dealloc 中释放它。
- 代表被分配,而不是保留
但我不明白的是我是否应该保留从另一个实例传递的内容。我知道风险在于保留计数下降到零,而我只能拿着袋子(或留下许多额外的袋子和内存),但是......我应该如何组织我的应用程序,以免发生这种情况?
我见过一些相关问题,但没有什么普遍性的。
当我在这里:那些已添加到 UIWindow
或 UIView
中但我个人并未保留的内容又如何呢?如果他们的超级视图从所有超级视图中删除,“自然”保留的实例是否会被释放?
I finally understand whether I must release an object, and how to keep my retain counts as low as possible in a trivial application (by knowing whether the object comes back with an extra 'retain' already called or not). So the NARC rules are working pretty well in that regard.
On the other hand, I can't wrap my head around whether to retain
(using retain properties, usually) or just assign
instance variables. Are there any rules of thumb there? I know of only two:
- If I made the instance within my class (e.g., in an init), then I should retain it and release it in the
dealloc
. - Delegates get assigned, not retained
But what I don't understand is whether I should retain stuff that I have passed from another instance. I know that the risk is that the retain count goes down to zero and I am left holding the bag (or left holding many extra bags and memory), but... how should I organize my application so that this doesn't happen?
I've seen some related questions, but nothing general.
While I'm Here: What about things that have been added to a UIWindow
or UIView
that I am not personally retaining? If their superview gets removed from all superviews, will the "naturally" retained instances get deallocated?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于类类型对象,您希望:
保留
复制
如果需要分配
弱引用至于清理,所有
retain
和copy
属性都需要release
。问题不在于它是否是在您的类的方法中创建的,而是您是否:
如果您尚未拥有它并想要对它进行强引用,请保留 - 这是对于传递到方法中的实例也是如此。无论您是通过 setter 显式保留还是隐式保留并不重要。
For class-type objects you want to:
retain
per defaultcopy
if the class is from a mutable/immutable class-clusterassign
if you need weak referencesAs for cleanup, all
retain
andcopy
properties need to bereleased
.The question isn't whether it was created in a method of your class, but whether you:
If you don't own it yet and want a strong reference to it, retain - this is also true for instances passed into your methods. Whether you retain explicitly or implicitly through a setter doesn't matter.
我不明白这一点。是什么让您认为您需要担心保留计数?保留计数是一个实现细节,忘掉它吧。您需要担心的是您是否拥有一个对象。
在几乎所有情况下,您在分配实例变量时都希望保留或复制。主要的例外是循环引用。有时,您会发现自己处于这样的情况:对象 A 具有对对象 B 的引用,而对象 B 具有对对象 A 的引用。如果 A 保留 B 并且 B 保留 A,则不能依赖 dealloc 中释放引用的正常模式来他们走开。在这种情况下,通常指定一个对象为所有者,而另一个对象为被拥有者。这样,所拥有的对象将不会保留其对所有者的引用。
一个示例是树结构,其中父节点具有对其子节点的引用,并且每个子节点都具有对其父节点的引用。如果每个子级都保留其父级,则当与父级的应用程序完成时,它不会消失,因为它已被所有子级保留。因此,父引用被实现为弱引用,这意味着子引用不会保留其父引用。
这是一种非常常见的委托模式,对象的所有者将自己设置为对象的委托。例如,表视图的控制器通常也是表视图的数据源和/或委托。如果表视图保留了委托,您将有一个保留周期(因为控制器已经保留了视图)。这就是“代表不留”惯例的产生。
如果您想要引用的对象实现 NSCopying 并且您需要在拥有所有权时不更改它,那么您绝对应该复制。 Cocoa 的一个例子是 NSDictionary 中元素的键。如果字典中的键发生变化,那将是一场灾难。所以 NSDictionary 复制它的键。
简单:遵循 Cocoa 内存管理规则。如果某些东西在你持有对它的引用时消失了,那么你并不拥有该东西。如果您需要某些内容的保留时间超过当前方法的范围,则应该保留它。
I don't understand this. What makes you think you need to worry about retain counts at all? The retain count is an implementation detail, forget about it. All you need to worry about is whether you own an object.
In almost all cases you want to retain or copy when you assign instance variables. The main exception is retain cycles. Sometimes, you find yourself in a situation where object A has a reference to object B and object B has a reference to object A. If A retained B and B retained A, you cannot rely on the normal pattern of releasing references in dealloc to make them go away. In this situation, it is usual to nominate one object as the owner and the other as the owned. The owned object would then not retain its reference to the owner.
An example of this would be a tree structure where the parent node has references to its children and each child has a reference to its parent. If each child retained its parent, when the application is done with the parent, it won't go away, because it has been retained by all its children. So the parent reference is implemented as a weak reference which means that the child does not retain its parent.
It's a very common pattern with delegates for the owner of an object to set itself as the object's delegate. For example, the controller of a table view is often also the table view's data source and/or delegate. If the table view retained the delegate you would have a retain cycle (since the controller has already retained the view). This is why the convention "delegates aren't retained" has arisen.
You should definitely copy if the object you want a reference to implements NSCopying and you need it not to change while you have ownership. An example from Cocoa is the keys of elements in an NSDictionary. If the keys were to change while in the dictionary, it would be a disaster. So NSDictionary copies its keys.
Simple: follow the Cocoa memory management rules. If something goes away while you are holding a reference to it, you did not own that something. If you need something to hang around for longer than the scope of the current method, you should retain it.