views:

121

answers:

2

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:

  1. If I made the instance within my class (e.g., in an init), then I should retain it and release it in the dealloc.
  2. 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?

+7  A: 

For class-type objects you want to:

  • retain per default
  • copy if the class is from a mutable/immutable class-cluster
  • assign if you need weak references

As for cleanup, all retain and copy properties need to be released.

If I made the instance within my class (e.g., in an init), then I should retain it and release it in the dealloc.

The question isn't whether it was created in a method of your class, but whether you:

  • want a strong reference to an instance
  • already own it

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.

Georg Fritzsche
Great stuff +1. I think the link is a very good one too.
Yar
"retain per default"? did you mean retain is the default attribute? If that is the case, you are mistaken. As assign is the default one.
Comptrol
@comp: " *you want to* retain per default" - i.e. you want to use `retain` properties except when [...].
Georg Fritzsche
@George Best, thanks for the clarification!
Comptrol
+1  A: 

how to keep my retain counts as low as possible

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.

I can't wrap my head around whether to retain (using retain properties, usually) or just assign instance variables.

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.

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?

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.

JeremyP
Thanks for sharing, it's nice to hear another version of the same thing, just to understand it better. I do not worry about retain counts whatsoever, but without keeping them in mind (at least), it's hard to understand why I would worry about releasing much at all. It's to keep the retain count low = lower memory footprint.
Yar