Notes on Memory Management in Objective-C - FMM(Frequently made mistakes)

To understand memory management is one thing (if it's no THE thing )you will be happy to know if you are or aim to be developer.
Cases like: developing a big project in mobile devices like the iPhone and then you realize you are running out of memory or writing a simple app that suddenly crashes!
These might take hours of debugging to solve and I remember myself not so long time ago thinking - I wouldn't have this problem is I knew memory management rules well from the beginning -.

Everything remains in the object's retainCount and its ownership. This is what I am reviewing here.

Initializing Objects:
You can initialize an object using a alloc init methods, like:

So, what is the difference?
When you use alloc/init to create an object you own it. Owning and object or having its ownership implies that you are responsible of releasing it. When using init method the object is initialized and its retainCount is set to 1 and the system won't release it for you.
An object can be owned by one or more objects, implying that each of these owners must release it.

When you use one of many convenience methods like -arrayWithObjects: to create you object, you don't own that object. Why? Initialization might be the same, but the difference is that object will be added to an auto-release pool. Hence when the pool gets drained your object will be released also. (Actually, objects are often released earlier when they are not needed anymore)

That was the super easy part. Now let's see how to pass an object we created to other objects' property.

Retain, assign or copy?

Consider the following code:@interfaceUITextView : UIScrollView{

...

}

@property(nonatomic,assign) id delegate;;

@property(nonatomic,copy) NSString *text;

@property(nonatomic,retain) UIFont *font;

@property (readwrite, retain) UIView *inputView;

This is part of UITextView class in iOS SDK. Suppose we have an instance textView.

Retain: the passed object will be retained (its retainCount will increase generally by 1). Here, textView will own the objects passed to font and inputView property.

Assign: the passed object will not be retained, (This is the default). If you don't set explicitly "retain" or "copy" then "assign" attribute will be assumed.

Copy: the passed object will be copied (generally a deep copy) Hence textView will own the object passed through text property. But the passed object and the retained object would be the same. When you have a deep copy it does not matter how you change the object from outside textView, it won't have effect, because it not same object as the one stored by text property. It's a mere copy.

Some of these are very silly, a couple of them is just to show memory leaks in Instruments, but I see very often people write code like this in some programming boards and they are very illustrative.

A is just the initialization of our instance. This is not about properties.

B, C, D are samples regarding "copy" property attribute. This is the case of text property.

B is correct. Allocate and initialize myText2 (retainCount is 1), is then passed through text property then is copied, and since needed no more it's released. No leaks, we are fine.

C is wrong. You might be tempted to shorten your B code like C but this will cause memory leaks.
Reason: When you allocate and initialize your object it will have retainCount 1 and right after that it is passed through text property then is copied and you don't have a reference to release!. This will be be more clearer in D.

D is just for illustrative purposes, you surely never want to do this. I did this just to make the leak very obvious in Instruments.
This is what I got in Instruments: pretty bad huh? Got 5 MB leaking (since my file size is 5KB)

Fig 1: Instruments showing leaked memory.

E and F are samples regarding "retain" property attribute. This is the case of inputView property.

E is correct, is basically like B, just this time keyboard is not copied, is the same object with it's retainCount increased. The big difference with copy is that if you change keyboard after you pass it to textView.inputView it will do have effect on textView 's input view because is the same object.

F is wrong, is very similar to C, just this time the object you created using alloc and initWithFrame: methods is the same as the one stored through inputView property. Hence you have a reference and could solve this leak later (by doing [textView.inputViewrelease];) but it will be ugly to my taste.

G is correct, this is what you want if you want to shorten E or correct F. I would use E rather than G.

H and I are samples regarding retain/copy but when using not owned objects. (object that will be autoreleased by an auto-release pool)

H is fine. In C, the bug was that object created just before passing it thought text property would not be released, but using the convenience method: -stringWithContentsOfFile:encoding:error: instead of initWithContentsOfFile:encoding:error: the problem is solved.
Why? when using those convenience methods the object returned is automatically polled in the most recent autorelease pool.How do I recognize a convenience method?the rule is simple: if the word "init" is present in the method name (signature) then you will have the ownership of the object, meaning that you have to release it by yourself. Otherwise, is a convenience method, you will not have the ownership of the object because it will be added to an autorelease pool. You don't need to release it.

I is just to show that using this approach won't leak memory as D
This is what I got in Instruments:

Since I am allocating 100 times the same object then Allocations instrument shows a big amount of memory allocated at the beginning (shown in Fig 2). But since that memory is owned by the system, is drained when is not needed anymore (when the app finished loading), as shown in Fig 3

J,K and L are to show "assign" property attribute.
Assign behaves like retain in the sense is the same object (not a copy) is stored. The difference is that the object passed is not retained.

J is not wrong from the memory management point of view, but is not what you want because textView property will not retain myDelegate object. Hence releasing myDelegate right after setting the delegate through inputView property is meaningless, because the object will be deallocated.

K is what you want to do instead of J. This is correct.

L is the shortened version of K, since delegate property attribute is assign, textView will not retain myDelegate. Hence allocating and initializing and object and passing it is not a problem like in C or F.

So why assign this useful? it depends on your needs actually. The most famous usage is a delegate.
If object X retain an object Y that retains X, both objects will never be released, this is also a memory problem. you create objects that cannot be released. In this case assign becomes useful.

With this I've finished this quite long post. I hope it helped a little bit someone.
Actually I wanted to write also about how to write your own classes with properties, how to properly initialize and release them, but this post is too long already. A new post is better ;)