Circular Reference and ARC

Automatic Reference Counting (ARC) is great. But, a common programming practice of circular referencing can easily introduce memory leak.

Let’s say that there are two objects – A and B. If A has a strong reference to B and B has a strong reference back at A, ARC will not be able to release these objects. This pattern occurs commonly in iOS code. A view controller object creates and keeps a reference to a Data Access Object (DAO). The DAO object keeps a reference to the view controller as a delegate. This way, neither of them will ever be destroyed.

The solution is to have one of the objects use weak reference.

Let’s first see the problem in action. Class A and B are defined as follows.

@interface A : NSObject
@property (nonatomic, strong) NSObject* b;
@end

@implementation A
@end

@interface B : NSObject
@property (nonatomic, strong) NSObject* a;
@end

@implementation B
@end

We write some code like this.

int main(int argc, const char * argv[]) {
    A *a = [[A alloc] init];
    B *b = [[B alloc] init];

    //a and b now have ref count 1

    a.b = b;
    b.a = a;

    //a and b have now ref count 2
}
    //a and b have now ref count 1

With this code, you have a memory leak. For both object a and b the reference count will at most go down to 1 and they will never be released.

The solution is to make one of the references to weak.

@interface B : NSObject
@property (nonatomic, weak) NSObject* a;
@end

A weak reference does not add a new reference count. It simply does a variable assignment.

The code will now run as follows:

int main(int argc, const char * argv[]) {
    A *a = [[A alloc] init];
    B *b = [[B alloc] init];

    //a and b now have ref count 1

    a.b = b;
    b.a = a;

    //a now has ref count 1. b has 2
}
    //a and b have now ref count 0 and destroyed

Going back the view controller and DAO classes, it is a good idea for the DAO to have a weak reference back at the controller (delegate). This is safe because the controller has a longer lifespan than the DAO. As a general rule, I will suggest, if class A and B have circular reference and class A creates an instance of B then A should have a strong reference and B should have a weak reference. This is strictly based on the fact that an object of class A has a longer lifespan that the object of class B that it creates.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s