Cocoa Programming/Memory management

From Wikibooks, open books for an open world
Jump to: navigation, search
Cocoa Programming
First Steps | Objective-C basics | Memory Management | Foundation Kit | Application Kit | Web Kit

Someone, please fix this page

Dynamic allocation[edit]

In Objective-C (unlike in C++), all objects are created dynamically. This means that they continue to exist until they are explicitly destroyed.

To create an object, send its class an alloc message: [aClass alloc];. Note that this returns a new instance of the class but does not initialize its data. Typically you want to immediately send the new object an init message to remedy this. Allocation and initialization are usually combined in one line:

aClass *newobj = [[aClass alloc] init];

There is a class method called new which allocates and provides a bare-bones initialization of the object, but has been deprecated in favor of alloc and init.

Reference counts[edit]

In C++, every dynamically created object needs to be explicitly deleted (using the delete operator). In Java, every dynamically created object (that is, every object) will be automatically deleted when the garbage collector detects that the object is no longer referenced. In Objective-C neither of these approaches is used.

An Objective-C object keeps a reference count. When an object is created, its reference count is initialized to 1. When the reference count reaches zero, the object will self-destruct.

Release[edit]

To tell an object that you will no longer use it, send it a release message: "[anObject release];". This decrements the object's reference count by one. If you were the last user of the object, the object will destroy itself.

After sending release to an object it is not safe to use that object anymore since the object may have self-destroyed.

Retain[edit]

When you want to retain an object, i.e. prevent it from disappearing, send it a retain message: "[anObject retain];". Note that you should not send a retain message to an object you have created with an alloc message, because alloc always implies retain. Therefore, retain is only needed, if you need to use an object that is created elsewhere (and will be sent the release message from there when it's not needed in that part of the program anymore).

Equilibrium[edit]

Every retain needs to be matched by one and only one release. Note that the new, alloc, copy, and mutableCopy methods also implicitly retain the returned object, so those methods also need to be balanced with release.

Autorelease pool[edit]

Sometimes an object cannot be released immediately: for example, a function creates an object and wants to return it to the caller. Now, the callee should release the object it has created and won't be using anymore. However, the caller need to get access to the returned object. If the callee would release the created object, the caller would never see the return value. One solution is to skip releasing the object in the callee and demand that the caller will release it. This is error-prone and breaks the principle of "match every retain with one release".

In Objective-C/OpenStep runtime, it is possible to send an object an autorelease message. This will cause the object to be added to the current autorelease pool. Objects in an autorelease pool will be released at some point in the future (when the current autorelease pool is destroyed). They are safe to use prior to that.

If the caller wants to keep the returned object, it must retain it. Otherwise, the object will be automatically released. Example:

  /* In class Environment, responsible of telling details of current environment: */
  - (id) nameOfLang        /* the callee */
  {
      id name = [[NSString alloc] initWithCString: "Objective-C"];
      [name autorelease];
      return name;
  }
  /* In another class where environment info is needed */
  - (void) getName        /* the caller */
  {
      myLangName = [environment nameOfLang];   /* myLangName is an instance variable */
      [myLangName retain];              /* Will be released when this object no longer needs it */
  }