What You Should Know about the Deadly Retain Cycle for iOS App Development - dummies

What You Should Know about the Deadly Retain Cycle for iOS App Development

By Neal Goldstein, Dave Wilson

ARC works very well to manage memory for your iOS app except in one circumstance. You need to understand 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’s an instance variable, it will stay in scope until the object itself is deallocated.

You’re going to go through this process using a little program called RetainCycle.

Create a new RetainIt object in the viewDidLoad method of your RetainCycleViewController object. It will be released only when the retainIt variable goes out of scope (it’s __strong by default). In this case, it will be released and then deallocated (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];}

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

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

You also, 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;–d

This means that the RetainIt object won’t be deallocated until the Cycle object is deallocated, and the Cycle object will be deallocated only when the RetainIt object is deallocated. Whoops!

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).

image0.jpg

The __weak lifetime qualifiers for objects take care of this. The solution is to make the lifetime qualifier back pointer __weak.

@property (weak, nonatomic) RetainIt* retainIt;