CHAPTER 4

Unlike C#, Objective-C does not use garbage collection. Instead, it uses a reference-counting environment that tracks how many places are using an object. As long as there is at least one reference to the object, the Objective-C runtime makes sure the object will reside in memory. However, if there are no longer any references to the object, the runtime is allowed to release the object and use the memory for something else. If you try to access an object after it has been released, your program will most likely crash.
There are two mutually exclusive ways to manage object references in Objective-C:
ARC is the preferred way to manage memory in new applications, but it’s still important to understand what’s going on under the hood. The first part of this chapter shows you how to manually track object references, and then we’ll talk about the practical implications of ARC.
This opens a window to let you adjust the build settings for the project. We’ll discuss build settings in the second half of this series. For now, all we need to find is the ARC flag. In the search field in the upper-right corner, type automatic reference counting, and you should see the following setting appear:
Click the arrows next to Yes and change it to No to disable ARC for this project. This will let you use the memory management methods discussed in the following paragraphs.
Manual memory management (also called manual retain-release or MMR) revolves around the concept of object “ownership.” When you create an object, you’re said to own the object—it’s your responsibility to free the object when you’re done with it. This makes sense, since you wouldn’t want some other object to come along and release the object while you’re using it.
Object ownership is implemented through reference counting. When you claim ownership of an object, you increase its reference count by one, and when you relinquish ownership, you decrement its reference count by one. In this way, it’s possible to ensure that an object will never be freed from memory while another object is using it. NSObject and the NSObject protocol define the four core methods that support object ownership:
For every alloc or retain method you call, you need to call release or autorelease at some point down the line. The number of times you claim an object must equal the number of times you release it. Calling an extra alloc/retain will result in a memory leak, and calling an extra release/autorelease will try to access an object that doesn’t exist, causing your program to crash.
All of your object interactions—regardless of whether you’re using them in an instance method, getter/setter, or a stand-alone function—should follow the claim/use/free pattern, as demonstrated in the following sample:
Included code sample: Manual Memory
int main(int argc, const char * argv[]) {
// Claim the object.
Person *frank = [[Person alloc] init];
// Use the object.
frank.name = @"Frank";
NSLog(@"%@", frank.name);
// Free the object.
[frank release];
return 0;
}
The [Person alloc] call sets frank’s reference count to one, and [frank release] decrements it to zero, allowing the runtime to dispose of it. Note that trying to call another [frank release] would result in a crash, since the frank variable no longer exists in memory.
When using objects as a local variable in a function (e.g., the previous example), memory management is pretty straightforward: simply call release at the end of the function. However, things can get trickier when assigning properties inside of setter methods. For example, consider the following interface for a new class called Ship:
Included code sample: Manual Memory – weak reference
// Ship.h
#import "Person.h"
@interface Ship : NSObject
- (Person *)captain;
- (void)setCaptain:(Person *)theCaptain;
@end
This is a very simple class with manually defined accessor methods for a captain property. From a memory-management perspective, there are several ways the setter can be implemented. First, take the simplest case where the new value is simply assigned to an instance variable:
// Ship.m
#import "Ship.h"
@implementation Ship {
Person *_captain;
}
- (Person *)captain {
return _captain;
}
- (void)setCaptain:(Person *)theCaptain {
_captain = theCaptain;
}
@end
This creates a weak reference because the Ship instance doesn’t take ownership of the theCaptain object when it gets assigned. While there’s nothing wrong with this, and your code will still work, it’s important to understand the implications of weak references. Consider the following snippet:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Ship.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *frank = [[Person alloc] init];
Ship *discoveryOne = [[Ship alloc] init];
frank.name = @"Frank";
[discoveryOne setCaptain:frank];
NSLog(@"%@", [discoveryOne captain].name);
[frank release];
// [discoveryOne captain] is now invalid.
NSLog(@"%@", [discoveryOne captain]. name);
[discoveryOne release];
}
return 0;
}
Calling [frank release] decrements frank’s reference count to zero, which means the runtime is allowed to deallocate it. This means that [discoveryOne captain] now points to an invalid memory address, even though discoveryOne never released it.
In the sample code provided, you will observe that we have added a dealloc method override in the Person class. dealloc is called when memory is about to be released. We should typically handle dealloc and release any nested object references that we hold. In this instance we will release the nested name property that we hold. We will have more to say about dealloc in the next chapter.
If you were to try to access the property, your program would most likely crash. As you can see, you need to be very careful tracking object references when you use weakly referenced properties.
For more robust object relationships, you can use strong references. These are created by claiming the object with a retain call when it is assigned:
Included code sample: Manual Memory - strong reference
- (void)setCaptain:(Person *)theCaptain {
[_captain autorelease];
_captain = [theCaptain retain];
}

The autorelease method works much like release, except the object’s reference count isn’t decremented immediately. Instead, the runtime waits until the end of the current @autoreleasepool block to call a normal release on the object. This is why the main.m template is always wrapped in an @autoreleasepool—it makes sure all objects queued with autorelease calls are actually released at the end of the program:
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Insert code to create and autorelease objects here.
NSLog(@"Hello, World!");
// Any autoreleased objects are *actually* released here.
}
return 0;
}
The idea behind auto-releasing is to give an object’s owner the ability to relinquish ownership without actually destroying the object. This is a necessary tool in situations where you need to return a new object from a factory method. For example, consider the following class method defined in Ship.m:
+ (Ship *)shipWithCaptain:(Person *)theCaptian {
Ship *theShip = [[Ship alloc] init];
[theShip setCaptain:theCaptian];
return theShip;
}
This method creates, configures, and returns a new Ship instance. But there’s a serious problem with this implementation: it results in a memory leak. The method never relinquishes ownership of the object, and callers of shipWithCaptain don’t know that they need to free the returned object (nor should they have to). As a result, the theShip object will never be released from memory. This is precisely the situation autorelease was designed for. The proper implementation is shown here:
+ (Ship *)shipWithCaptain:(Person *)theCaptian {
Ship *theShip = [[Ship alloc] init];
[theShip setCaptain:theCaptian];
return [theShip autorelease]; // Must relinquish ownership!
}
Using autorelease instead of an immediate release lets the caller use the returned object while still relinquishing ownership of it in the proper location. If you remember from the Data Types chapter, we created all of our Foundation data structures using class-level factory methods. For example:
NSSet *crew = [NSSet setWithObjects:@"Dave", @"Heywood", @"Frank", @"HAL", nil];
The setWithObjects method works exactly like the shipWithCaptain method described in the previous example. It returns an autoreleased object so that the caller can use the object without worrying about memory management. Note that there are equivalent instance methods for initializing Foundation objects. For example, the crew object in the last sample can be manually created as follows:
// Create and claim the set.
NSSet *crew = [[NSSet alloc] initWithObjects:@"Dave", @"Heywood", @"Frank", @"HAL", nil];
// Use the set...
// Release the set.
[crew release];
However, using class methods like setWithObjects, arrayWithCapacity, etc., is generally preferred over the alloc/init.
Dealing with the memory behind an object’s properties can be a tedious, repetitive task. To simplify the process, Objective-C includes several property attributes for automating the memory management calls in accessor functions. The attributes described in the following list define the setter behavior in manual reference-counting environments. Do not try to use assign and retain in an automatic reference counting environment.
As a simple example, examine the following property declaration:
@property (retain) Person *captain;
The retain attribute tells the associated @synthesize declaration to create a setter that looks something like:
- (void)setCaptain:(Person *)theCaptain {
[_captain release];
_captain = [theCaptain retain];
}
As you can imagine, using memory management attributes with @property is much easier than manually defining getters and setters for every property of every custom class you define.
Now that you’ve got a handle on reference counting, object ownership, and autorelease blocks, you can completely forget about all of it. As of Xcode 4.2 and iOS 4, Objective-C supports automatic reference counting (ARC), which is a pre-compilation step that adds in the necessary memory management calls for you.

Automatic reference counting works by examining your code to figure out how long an object needs to stick around and inserting retain, release, and autorelease methods to ensure it’s deallocated when no longer needed, but not while you’re using it. So as not to confuse the ARC algorithm, you must not make any retain, release, or autorelease calls yourself. For example, with ARC, you can write the following method and neither theShip nor theCaptain will be leaked, even though we didn’t explicitly relinquish ownership of them:
Included code sample: ARC
+ (Ship *)ship {
Ship *theShip = [[Ship alloc] init];
Person *theCaptain = [[Person alloc] init];
[theShip setCaptain:theCaptain];
return theShip;
}
In an ARC environment, you should no longer use the assign and retain property attributes. Instead, you should use the weak and strong attributes:
You can see the difference between weak and strong using the implementation of the ship class method from the previous section. To create a strong reference to the ship’s captain, the interface for Ship should look like the following:
// Ship.h
#import "Person.h"
@interface Ship : NSObject
@property (strong) Person *captain;
+ (Ship *)ship;
@end
And the implementation Ship should look like:
// Ship.m
#import "Ship.h"
@implementation Ship
@synthesize captain = _captain;
+ (Ship *)ship {
Ship *theShip = [[Ship alloc] init];
Person *theCaptain = [[Person alloc] init];
[theShip setCaptain:theCaptain];
return theShip;
}
@end
Then, you can change main.m to display the ship’s captain:
int main(int argc, const char * argv[]) {
@autoreleasepool {
Ship *ship = [Ship ship];
NSLog(@"%@", [ship captain]);
}
return 0;
}
This will output something like <Person: 0x7fd6c8c14560> in the console, which tells us that the theCaptain object created in the ship class method still exists.
But, try changing the (strong) property attribute to (weak) and re-compiling the program. Now, you should see (null) in the output panel. The weak reference doesn’t ensure that the theCaptain variable sticks around, so once it arrives at the end of the ship class method, the ARC algorithm thinks that it can dispose of theCaptain. As a result, the captain property is set to nil.
Memory management can be a pain, but it’s an essential part of building an application. For iOS applications, proper object allocation/disposal is particularly important because of the limited memory resources of mobile devices. We’ll talk more about this in the second part of this series, iOS Succinctly.
Fortunately, the new ARC scheme makes memory management much easier on the average developer. In most cases, it’s possible to treat an ARC project just like the garbage collection in a C# program—just create your objects and let ARC dispose of them at its discretion. Note, however, that this is merely a practical similarity—the ARC implementation is much more efficient than garbage collection.