Monday, December 15, 2008

iPhone Application Development: Memory Management with Objective-C / Cocoa

This discussion touches the basics of memory management within Objective-C / Cocoa. Hopefully, you have already ready my post about differences between C++ / Java and Objective-C.

Cocoa library (and thus Cocoa Touch for iPhone Development) defines NSObject, which is at the root of the entire class hierarchy of the Foundation framework. Every other framework, depends on the Foundation Framework. NSObject implements a semi-automated / reference counting version of garbage collection. Memory manager might be a more appropriate name.

Here is some sample code that helps illustrate how to use NSObject's garbage collection mechanism:

#import <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSObject *obj = [[NSObject alloc] init];
NSLog(@"Created object %@", obj);
[obj release];

[pool release];
return 0;
}
NSObject provides the following messages to manage objects via the memory-manager:
  • alloc: Create a new object. Allocates physical memory for the object. This message to be passed to the class. Alloc "retains" the object. i.e. Objects created by alloc have a reference count of 1. Be sure to release it when you are done.
  • init: initializes the object. It is considered best practice to always init the object by sending it the init message. Typical object creation looks like MyClass *obj = [[MyClass alloc] init]; - calls both alloc and init.
    • If you override init, it must always return itself (id). Sample code: if (self = [super init]) { /* my inits */ } return self;
  • dealloc: Free the memory obtained by alloc. Avoid calling dealloc. Always call release - let the memory manager perform dealloc, when appropriate.
  • retain: Signal to the garbage collector that we are intrested in this object. This increases the reference counter for this object by one.
  • release: Signal to the garbage collector that we are no longer interested in this object. This decreases the reference counter by one. When the reference counter reached 0, the object is deallocated. As a general rule, always "release" pointers holding memory. This will let the memory-manager do its job.
NOTE: If you do decide to over-ride any of these methods, be sure to call super's corresponding method at the appropriate time.

Creating an NSAutoReleasePool creates and inits the memory-management system. At the end of the program, the release message to the auto-release pool signals that we are no longer interested in it. The system then disposes off the auto-release pool, and sends release message to all the objects it contains. Any object that gets to a reference count of 0, is deallocated.

General Tips / Rules of thumb related to memory management
  • Classes should override dealloc, if they want to be notified of when the object is put out of its misery. This is an appropriate place for the object to release any memory that it may have allocated. Be sure to call parent's dealloc when you are done.
  • In setters, always retain the new object first, then release the old object. This will take care of cases when the same value is being set over and over again.
  • Maintain atleast one Auto release pool per thread
  • If you have to create an object and return it from a method. Make sure you pass the autorelease method to it. This will add the object to the autorelease pool.
  • This leads to: don't release objects that you receive from other messages. Assume that they have been added to the auto release pool by the creator. release them *only* if you retain them for some reason.
  • Write memory balanced code: total count of alloc, copy, mutableCopy should be equal to the total count of release, autorelease
  • Every collection retains an object when its added, and releases it when it is removed. Releasing a collection object releases all the objects stored in it as well.
  • NSString objects created using @"..." should be considered as constants. retain or release messages have no effect on them.

No comments:

Post a Comment