Starting from Xcode 4.2 and the introduction of the new LLMV compiler, is now possible to use “Automatic Reference Counting” (ARC). This powerful feature frees developers from memory management by eliminating the need of sending release and autorelease messages. Anyway this is very different from a garbage collector, in that it’s a compile-time feature, which basically analyze the code and automatically inserts that calls when necessary for us. In this way we have the best of two worlds: we don’t have to worry about releasing, deallocations and memory leaks, but simultaneously we have the performance of a memory managed language. This is very cool, however I don’t envy new upcoming iOS developers whose will start directly using ARC. It’s very important learning and understanding how memory management works in Objective c, and the difference between owning a reference to an object or not (I recommend this reading). For example I fear that new developers won’t understand the use and benefits of NSAutoreleasePool (that have been replaced with @autorelease block in ARC).
Anyway in the last days I switched my code to ARC using Xcode refactor system and I want to share my experience.
These are the steps I followed:
1. “Preferences” -> “General” -> check “continue building after error”
This step is fundamental to avoid an huge waste of time repeating the next steps every time an error is encountered!
2. “Edit” -> “Refactor” -> “Convert to Objective-C ARC”
3. “Select targets to convert” (check them)
4. Click “precheck”
5. “Cannot Convert to Objective-C ARC” (Xcode found N issues that prevent conversion from proceeding. Fix all ARC readiness issues and try again.)
You will see this message at least once, because your code contains calls that are forbidden by ARC.
6. Fix them using suggestions (click on errors to open the popup containing the tip). Then repeat from step 1
7. “Convert to automatic reference counting” window will appear (once issues have been fixed)
8. Click next
9. Review automatic changes
If after clicking on “save” nothing happens, you may be unlucky as I am and Xcode is unable to prooced because it silently fails trying to generate a snapshot of your project. I solved the problem by doing a clean install, that means run “sudo /Developer/Library/uninstall-devtools” to remove all files and install Xcode from the scratch (by the way this had also improved its performances).
The migration was pretty painless in my case, however I had to disable ARC on certain files because it was very hard to refactor the code in order to make it ARC-friendly (this is the case for heavy use of Core Foundation functions).
To disable ARC in these files I added the flag “-fno-objc-arc” in the column “compiler flags” under “Build phases” tab (related to my target).
I then did a small refactor by marking NSError pointer as “autoreleasing”:
NSError *__autoreleasing error = nil;
This is in fact a little optimization trick, that avoid the creation of an extra temporary variable by the compiler. (read more here).
I also marked all readonly properties as “strong” and removed the “__unsafe_unretained” placed by Xcode.
…that’s all folks… all works pretty well, the code is shorten and cleaner and I’m satisfied :)