Before I get to the post, let me drop this disclaimer: There is nothing in this post that violates NDA. I took all of the information for this post from the following documentation found online on the LLVM compiler’s website: Objective-C Automatic Reference Counting.
With the legal hoo-ha out of the way, let’s get down to the good stuff: ARC. If you’ve been developing for iOS or you’re even just vaguely familiar with it, then you know what reference counting is. I spend some time talking about the difference between Reference Counting and Garbage Collection in my Windows Phone 7 for iPhone Developers book and also talk about Reference Counting and ARC in my other (semi-top secret) upcoming book.
What it boils down to is that in an Object-Oriented application, especially one with multiple modules, lots of classes, and lots of exchanging of pointers to objects – you have a memory issue. The issue is – when a given class is done with a given object, how can it decide whether or not its OK to free the memory for that object? In short, it can’t. If you’ve designed your classes properly, they should have absolutely no way of knowing how many other objects in your application have a reference to the object in question. The classic Objective-C solution to this problem, and the one currently employed both on the Mac and in iOS, is Reference Counting. When an object declares its intent to hold onto another object for a period of time, it retains that object. When it says to the other object, “So long, and thanks for all the fish!”, it can then release the object when it’s done using it.
This is great and very efficient. The problem is, it’s also really easy to screw up. If you set an object to nil that has references to it, you’ve just created a memory leak. If you forget to release an object that goes out of scope, you’ve just created a memory leak. It’s scary easy to create memory leaks and sometimes can be scary hard to track them down, even with Instruments tools like Leaks.
Unfortunately, this is where many .NET developers start pointing fingers. They yell and scream and claim that reference counting is old-school. If these same .NET developers used to be COM developers, then they have plenty of reason to both fear and hate reference counting (on Windows). Many .NET developers (and Java developers, including Android devs) are so used to the idea of a garbage collector they can’t fathom the idea of having to manually manage their own reference counts. To them, it’s barbaric – we might as well be asking them to call malloc and dealloc manually! The horror!
Garbage Collection is a sort of omnipresent Big Brother figure. It hovers over your object graphs and when it thinks you’re not looking (e.g. the application’s CPU utilization might be low, or completely idle) it will sift through your memory and free up the memory for orphaned (these would be leaking in a ref-counted environment) objects. Some garbage collectors will tidy up the place while they’re at it and defrag the managed heap. This, of course, implies that there is a managed heap to begin with. There is no such managed heap in Objective-C and, at least on iOS, there is no garbage collector. Objective-C 2.0 (for the Mac) has the option of being garbage collected but there are performance implications to running under a GC.
Finally, now that we know what reference counting and garbage collection are.. what the heck is Automatic Reference Counting? In my humble opinion, ARC is the best of both worlds. The reason people love GC is because it frees the developer from spending so much time coding pomp and circumstance (retain, release, autorelease, *panic*, etc) so they can spend more time worrying about actual functionality. ARC also provides this benefit but it doesn’t require the overhead of a garbage collector!
So now, instead of manually retaining and releasing objects, you simply declare them. When you declare an object, you tell the compiler (and therefore, ARC) how you want the lifetime of that object managed. There are 4 ownership qualifications that you can specify when declaring an object (or defining a property):
- Autoreleasing – When an object is assigned, it is retained and autoreleased.
- Strong – The new object is retained and the old one is released. This is the standard “retain” behavior for properties in ObjC 2.0
- Unsafe retained – The object is simply stored in the variable.
- Weak – Weak references are non-retained but they also have an added benefit – if an object to which a weak reference refers has been de-allocated, the weak value is automatically set to nil, preventing an awful lot of crashes.
So now we can declare properties like this:
@property(strong) KCDemo *kotanCodeDemo;
And we can declare variables like this:
__weak KCDemo *kotanCodeDemo;
Since strong is the default, we automatically take care of reference counting for pointer objects just by declaring them:
There is a truckload more to Automatic Reference Counting than what I mentioned here. I just wanted to point it out so that .NET and Java developers who have spent so much time and effort lambasting the fact that iOS has no garbage collection see that there is a new option on the horizon and, in my opinion, that option is even better than garbage collection.