1.5 Memory Management

To properly manage memory, Cocoa provides a reference counting mechanism, supported by the NSObject and NSAutoreleasePool classes. As its name suggests, reference counting maintains a count of how many references there are to an objectindicating how many other objects are interested in keeping the object around. Reference counting is not automatic; the compiler has no way to determine an object's lifetime. Therefore, the following NSObject reference counting methods must be called to indicate the level of interest in an object to the memory management system:

retain

Increments the object's reference count by 1. When you want to register interest in an object that you did not create or copy, indicate interest in it by calling this method.

release

Decrements the object's reference count by 1. This message is sent to objects created with the alloc method or sent a retain message when you are no longer interested in using them. If this causes the retain count to reach 0, the runtime deallocates the object.

autorelease

Adds the object to the current autorelease pool. This allows you to release your interest in an object without immediately causing the retain count to reach 0. When the autorelease pool is itself released, it sends the release message to every object it contains. This is most useful when you want to pass the object to another object as a return value and won't have the opportunity to release the object later by yourself.

The following set of rules will help you perform accurate reference counting and avoid either leaking memory or prematurely destroying objects:

  • Objects created by alloc or copy have a retain count of 1.

  • If you want to keep an object received from another mechanism, send it a retain message.

  • When you are done with an object created by alloc or copy, or retained by the retain message, send it a release message.

  • When you add an object to a collection, such as an array or dictionary (described in Chapter 2), the collection retains it. You are no longer responsible for the object, and you may safely release any interest in it.

  • If you need to release interest in an object but need to ensure that it is not immediately destroyed, send an autorelease message so the object is put in the autorelease pool for later release.

Once you have released interest in an object, you shouldn't send any messages to it. If an object is deallocated because its retain count reached 0, sending a message to the object will cause an error.

1.5.1 Retaining Objects in Accessor Methods

Accessor methods require a bit of caution, especially those where an object's instance variables are set. Because an object passed to a set method may already be held, you must be careful about how memory management is performed. Releasing an object before retaining it can lead to unfortunate side effects and can be the source of much frustration. To ensure that memory management is performed correctly, send the autorelease method to an old object reference before replacing it with a new reference. Example 1-8 shows how this rule is applied in the Song class's setTitle: method.

Example 1-8. Memory management in accessor methods
- (void)setTitle:(NSString *)aTitle {
    [title autorelease];
    title = [aTitle retain];
}

Another way to ensure proper memory management and further increase encapsulation is to make a copy of the parameter, as shown in Example 1-9. This ensures that even if a mutable subtype of NSString were given, any modifications to that parameter would not change the contents of the title variable.

Example 1-9. Copying a parameter to enforce encapsulation
- (void)setTitle:(NSString *)aTitle {
    [title autorelease];
    title = [newTitle copy];
}

These practices ensure proper memory management in almost all situations you are likely to encounter. However, some fringe cases require care in handling. For more details, see http://www.stepwise.com/Articles/Technical/2002-06-11.01.html.



    Part II: API Quick Reference