Question

I've done a bit of reading and I've found a lot about how things are, but not why:

From what I have read, automatic reference counting makes memory management a lot easier than it would have been in the past. As I understand it, it is analogous to garbage collection in Java, the difference being that it is taken care of at compile time not run time. I.e. the compiler inserts code that keeps track of how many references an object has, then deallocates it when this count hits 0.

In the code I've written so far I've had quite a few problems with objects vanishing due to ARC deallocating them because I hadn't used a strong reference. My take away from these problems is... always always always use a strong reference!

So my question is why do weak references even exist? I.e. when would I as a developer ever want a reference to an object that I can't rely on not being deallocated without my knowledge?

Was it helpful?

Solution

Reference counting is not garbage collection.

In a reference counting system like Cocoa Touch, the system deallocates an object when its reference count becomes zero.

Now consider writing an app that uses a UITableView. You have to provide an object to act as the table view's data source. You will probably use your UIViewController subclass as the data source.

Your view controller probably has a reference to the table view. That means the table view's reference count is at least 1.

Your table view needs a reference to its data source. That means the view controller has a reference count of at least 1.

Suppose the view controller is no longer referenced by anything except the table view, and the table view is no longer reference by anything except the view controller. It is impossible for your program to ever use these objects again, because it has no path of references it can follow that will lead to either object. We can say that the objects are “inaccessible”. Even then, neither of the objects can be destroyed, because each has a reference count of 1.

In Cocoa Touch, this scenario is called a retain cycle. A retain cycle is bad (unless it will be broken automatically when some event happens, like a timer firing or a touch ending), because it prevents the system from destroying objects that will never be used again.

This is in fact the difference between reference counting and garbage collection: a GC collects all objects that your program can no longer access. A reference counting system collects all objects that have a reference count of zero.

You could try to write your program to notice when the view controller and table view are no longer needed. When that happens, you could explicitly break the retain cycle (for example, by setting the table view's data source to nil). But in general it's hard to know when none of the objects is reachable. (That is why garbage collectors are so nice: they do the hard work for you.)

In Cocoa Touch, to prevent the retain cycle in the table view example, the table view references its data source “weakly”. It keeps a reference to the data source, but it doesn't increment or decrement the data source's reference count. So when the view controller and the data source both become unreachable, the table view's reference count is still 1 (because the view controller has a strong reference to it), but the view controller's reference count is 0. So the system deallocates the view controller. During deallocation, the view controller gives up its reference to the table view, which makes the table view's reference count zero, so the system can also deallocate it.

In truth, the table view doesn't use an ARC weak reference (as far as I know). It uses what ARC calls an __unsafe_unretained reference, because it was written long before ARC. But you should use ARC weak references in your code, because they are much safer and more useful.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top