The iOS SDK from Apple introduces Automatic Reference Counting (ARC). You can now stop thinking about all those retain, release, and autorelease, so that you can focus on the code instead of memory management. ARC is available if you use the new and better LLVM 3.0 compiler. If you create a new project in Xcode 4.2, these are already used as defaults. For old projects created with previous versions of Xcode, you can choose Edit > Refactor > Convert to Objective-C ARC to ask Xcode to update all or some of your source files to use ARC. This means you can use ARC for application specific files but still use manual memory management for old libraries you developed or third-party libraries.
This sounds great, but there are always caveats as we all know it. The fact that the iOS SDK consists of both Objective-C and C libraries (e.g. Address Book, Core Foundation, Core Image, Core Graphics, …etc.) means we really need to have a good understanding of how manual memory management works to use ARC effectively.
When you use Edit > Refactor > Convert to Objective-C ARC, Xcode shows the changes it is about to make in a diff view. Instead of just clicking the Save button and let Xcode to update the sources. Let’s try to understand the changes it is trying to make, so that we won’t be surprised when the app fails to build or crash when run.
@property (nonatomic, retain) IBOutlet UILabel *label; @property (nonatomic, strong) IBOutlet UILabel *label;
What is the difference between retain and strong?
A retain property says to the compiler that the property should increment the reference count by 1 when it is set to an object. When you no longer needs the object, you need to call release on it before setting it to a new object. This is manual memory management.
A strong property means the property is a strong pointer to an object. If pointer A is a strong pointer and both pointers A and B point to the same object, when pointer B points is set to point to something else. Pointer A is still valid because it keeps a reference to the object it points to. However, if pointer A is a weak pointer, when pointer B is set to point to something else, pointer A becomes nil because it is too weak to keep the object alive.
What does this mean with ARC? A retain property should only be used when you are not using ARC, since you are expected to call release when you no longer needs the object the property points to. However, ARC handles calling release for us when it compiles, that means we are not supposed to call retain and in fact we cannot because the compiler would complain. Therefore, we tell ARC that the property is a strong property so when ARC detects it is no longer needed, it can release it for us.
If we were to declare the property as a weak property, since weak pointers do not keep the object alive, when it is set to point to an object and if it is the only pointer that points to that object, it will not hold the object, and we would get a crash.
As you can see, while ARC can help us handle most memory management and free us to develop the application. It does not mean we don’t need to understand memory management. In future episodes of this ARC series, I will point out more caveats of using ARC and what we need to understand deeper in order to use it correctly and effectively.
You can create a strong pointer using:
NSString *version = @"iPhone 4S"; __strong NSString *strongVersion = version;
NSString *version = @"iPhone 4S"; NSString *strongVersion = version;
since variables are strong by default. When you call [version release], strongVersion is still valid.
You create a weak pointer using:
NSString *version = @"iPhone 4S"; __weak NSString *weakVersion = version;
When you call [version release], weakVersion becomes nil.
You need to create delegate property as a weak property, like so:
@interface MyViewController : UIViewController @property (nonatomic, weak) id <MyDelegate> delegate; @end
This is important. If we were to declare the delegate as a strong property, when an object of MyViewController is created, it has a strong pointer to the MyDelegate delegate, and the MyDelegate delegate also has a strong pointer to the MyViewController object. When MyViewController is released, it needs to release MyDelegate. When MyDelegate is released, it needs to release MyViewController. It is a never-ending cycle! Therefore, we need to make MyDelegate a weak pointer to MyViewController so that they can be properly released.
In Part 2, I will explain retain, release, and autorelease and why they aren’t needed anymore when you use ARC.