The subject of memory management is a difficult but essential lesson to learn. Without knowing how to allocate and de-allocate memory, you stand very little chance of building an app that will work correctly.
This is an explanation of how to allocate variables into memory and release them and should help you understand the basics of memory management with objects in Objective-C to help you avoid crashes and memory leaks.
Allocation of memory
In objective C the standard way to allocate a variable to memory is to use the alloc keyword, for example:
NSString *strVariableName = [[NSString alloc] initWithString:@”My String”];
The key ingredient here is [NSString alloc] which indicates that you wish to allocate the memory for this variable yourself.
When doing this YOU are responsible for un-allocating it from memory. If you do not do this, then the memory will be leaked.
If memory leaks then you cannot gain that memory allocation back and risk the application running out of memory if it happens frequently enough.
Therefore memory should always be cleared as soon as you know it isn’t going to be used anymore; by this I mean the variable in memory has to be un-allocated. For example;
[strVariableName release];
This method call on the string we created earlier releases the variable from memory and means the memory block is free for future allocation.
To create multiple instances of a variable, so that the variable is allocated to multiple elements in memory, the retain method should be called.
Dealloc
At the end of every class in Objective C should be a dealloc method which releases all unused variables from memory and clears the class down to the state that it was in before it was created – to null (or nill).
You should not call dealloc on a variable as it destroys it and the variable will loose any additional memory references in the process.
To remove a variable from memory, keep a count of the amount of instances the variable has (by counting the inital alloc method and then each additional retain on the variable will tell you how many releases you require. For example;
NSString *strMyVariable = [[NSString alloc] initWithString:@”My string”];
[strMyVariable retain]; // Retain count 2
[strMyVariable retain]; // Retain count 3
[strMyVariable release]; // Retain count 2
[strMyVariable release]; // Retain count 1
[strMyVariable release]; // Retain count 0
At the point of the retain count reaching 0 on a variable, the dealloc method is automatically called and the object is completely destroyed.
If the scope of the object in question is within a method, then call your release methods on the object at the end of the method. If the object’s scope is a for the whole class then add the release method calls to the
– (void) dealloc method at the end of the class. This will ensure that when the class is deconstructed, the memory is released.
Automatic allocation / deallocation of memory can be achieved by avoiding calls to the alloc method, for example;
NSString *strMyVariable = [NSString initWithFormat:@”%d”, 1.23];
This might seem like a good idea as it shouldn’t require you to remove the object from memory but it will give you less control over an object’s lifetime. The object will get cleared automatically but not at a point you may desire. Then when you come to call on it at a later time, the object may be removed from memory and no longer available, resulting in an application crash.
Likewise, you cannot call release on an object that isn’t declared as being managed manually as this will also cause an application crash.
Summary
Remember that when you want to control the lifetime of an object, first call the [object alloc] call the [object release] method at the end of its expected life, and if it’s scope is the entire class ensure it is released in the dealloc method.