Home / iPhone Tips and Tutorials

Working with variable types according to ARC

Because the reference to an object lives in a variable, object pointers can be qualified using ownership type or lifetime qualifiers. These qualifiers determine when the compiler can de-allocate an object to which a pointer points.

These qualifiers are as follows:

__strong
__weak
__unsafe_unretained
__autoreleasing

The following sections describe the function of each of these qualifiers.

__strong variables "retain" their values

__strong is the default. You almost never have to specify it and stack local variables, including parameters, are __strong. A __strong pointer to an object will cause that object to be retained while it is in scope (or not set to nil). No more dangling references (objects that have been de-allocated that you expect to be there)!

__weak variables don't retain values

__weak variables do not cause an object to be retained (that is, you don't use them in the reference count) and are, in fact, set to nil (zeroed) as soon as the referenced object starts de-allocating. You need to be concerned with these only to prevent retain cycles, which explain shortly.

__unsafe_unretained don't retain values and are not zeroed

There are some Apple-provided classes (only on the Mac and some thirdparty libraries) that don't work with zeroing weak references. These have to be cleared in a dealloc method elsewhere.

Tip:
Using ARC, strong, weak, and autoreleasing stack variables are now implicitly initialized with nil.

__autoreleasing for indirect pointers

These variables are not for general use. They are used for out parameters that pass values back to the calling routine They are retained and then autoreleased when they are read into.

Understanding the deadly retain cycle

ARC works very well to manage memory except in one circumstance. In this section, explain how that circumstance can arise, and what you'll need to do to keep it from happening.

When you create an object, the compiler makes sure that ownership is transferred and all is well. The compiler will release that object when it goes out of scope, so if it is an instance variable, it will stay in scope until the object itself is de-allocated.

This process using a little program called RetainCycle that illustrate the retain cycle.

Create a new RetainIt object in the viewDidLoad method of my Retain CycleViewController object. It will be released only when the retainIt variable goes out of scope (it is __strong by default). In this case, it will be released and then de-allocated (assuming that no other object takes ownership) at the end of viewDidLoad because the retainIt variable will go out of scope:

- (void)viewDidLoad
{
  [super viewDidLoad];
  RetainIt* retainIt = [[RetainIt new] init];
}

When create the RetainIt object, in the RetainIt class's initialization method, init, create a Cycle object and assign it to the cycle instance variable declared. As you might expect, the Cycle object will be retained until the RetainIt object is de-allocated because it is referenced by an instance variable, which stays in scope until the object is de-allocated:

- (id)init
{
  self = [super init];
  if (self) {
    self.cycle = [[Cycle new] init];
    cycle.retainIt = self;
  }
  return self;
}

However, assign to the Cycle object's retainIt property a reference back to the RetainIt object. The Cycle class looks like this:

@interface Cycle : NSObject

@property (strong, nonatomic) RetainIt* retainIt;

@end

This means that the RetainIt object will not be de-allocated until the Cycle object is de-allocated, and the Cycle object will be de-allocated only when the RetainIt object is de-allocated.

Although this example may appear a bit contrived, it actually can occur in real life when you have one object with a back pointer to the object that creates it (either directly or through a chain of other objects, each with a strong reference to the next leading back to the first).

The __weak lifetime qualifiers for objects takes care of this. Although I haven't explained properties yet, the solution is to make the lifetime qualifier back pointer __weak.

@property (weak, nonatomic) RetainIt* retainIt;
[Previous] [Contents] [Next]