Graphics Programs Reference
In-Depth Information
Every retain cycle can be broken down into a parent-child relationship. A parent typically
keeps a strong reference to its child, so if a child needs a pointer to its parent, that pointer
must be a weak reference to avoid a retain cycle.
A child holding a strong reference to its
parent's
parent also causes a retain cycle. So the
same rule applies in this situation: if a child needs a pointer to its parent's parent (or its
parent's parent's parent, etc.), then that pointer must be a weak reference.
It's good to understand and look out for retain cycles, but keep in mind that they are quite
rare. Also,
Xcode
has a
Leaks
tool to help you find them. We'll see how to use this tool in
An interesting property of weak references is that they know when the object they referen-
ce is destroyed. Thus, if the backpack is destroyed, the calculator automatically sets its
container
instance variable to
nil
. In
main.m
, make the following changes to see
this happen.
NSMutableArray *items = [[NSMutableArray alloc] init];
BNRItem *backpack = [[BNRItem alloc] init];
[backpack setItemName:@"Backpack"];
[items addObject:backpack];
BNRItem *calculator = [[BNRItem alloc] init];
[calculator setItemName:@"Calculator"];
[items addObject:calculator];
[backpack setContainedItem:calculator];
NSLog(@"Setting items to nil...");
items = nil;
backpack = nil;
NSLog(@"Container: %@", [calculator container]);
calculator = nil;
Build and run the application. Notice that after the backpack is destroyed, the calculator
reports that it has no container without any additional work on our part.
A variable can also be declared using the
__unsafe_unretained
attribute. Like a
weak reference, an unsafe unretained reference does not take ownership of the object it
points to. Unlike a weak reference, an unsafe unretained reference is not automatically set
to
nil
when the object it points to is destroyed. This makes unsafe unretained variables,
well, unsafe. To see an example, change
container
to be unsafe unretained in
BNRItem.h
.
__unsafe_unretained
BNRItem *container;
Build and run the application. It will most likely crash. The reason? When the calculator
was asked for its container within the
NSLog
function call, it obligingly returned its value