Beginning ARC in iOS 5 Tutorial Part 2
Note from Ray: This is the twelfth iOS 5 tutorial in the iOS 5 Feast! This tutorial is a free preview chapter from our new book iOS 5 By Tutorials. Matthijs Hollemans wrote this chapter – the same guy who wrote the iOS Apprentice Series. Enjoy! This is a post by iOS Tutorial Team member […] By Ray Wenderlich.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Beginning ARC in iOS 5 Tutorial Part 2
55 mins
Unsafe_unretained
We’re almost done covering the basics of ARC – I just wanted to mention one more thing you should know.
Besides strong and weak there is another new modifier, unsafe_unretained. You typically don’t want to use that. The compiler will add no automated retains or releases for variables or properties that are declared as unsafe_unretained.
The reason this new modifier has the word “unsafe” in its name is that it can point to an object that no longer exists. If you try to use such a pointer it’s very likely your app will crash. This is the sort of thing you used the NSZombieEnabled debugging tool to find. Technically speaking, if you don’t use any unsafe_unretained properties or variables, you can never send messages to deallocated objects anymore.
Most of the time you want to use strong, sometimes weak, and almost never unsafe_unretained. The reason unsafe_unretained still exists is for compatibility with iOS 4, where the weak pointer system is not available, and for a few other tricks.
Let’s see how this works:
@property (nonatomic, unsafe_unretained)
IBOutlet UITableView *tableView;
@property (nonatomic, unsafe_unretained)
IBOutlet UISearchBar *searchBar;
Run the app and simulate the low-memory warning.
Artists[982:207] Received memory warning. Artists[982:207] *** -[UITableView retain]: message sent to deallocated instance 0x7033200
Whoops, the app crashes. An unsafe_unretained pointer does not have ownership over the object it points to. That means the UITableView was not kept alive by this pointer and it got deallocated before viewDidUnload was called (its only owner was the main view). If this was a true weak pointer, then its value would be been set to nil. Remember, that was the cool feature of “zeroing” weak pointers. We saw that earlier when the NSLog() said “(null)”.
However, unlike a true weak pointer, an unsafe_unretained pointer is not reset to nil when the associated object dies. It keeps its old value. When you try to send a message to the object — which is what happens when you NSLog() it — you’re sending the message to an object that no longer exists. Sometimes this may accidentally work, if the memory for that object hasn’t been overwritten yet by another object, but often it will crash your app… which is exactly what we saw happening here. That should illustrate why these things are called “unsafe”.
Note: we caught this bug because I enabled zombies in the Diagnostics tab for this scheme. To see this settings panel, choose Product -> Edit Scheme… from the menubar.
Without this setting, the app may not have crashed at all, or it may have crashed at some later point. Good luck trying to figure that one out! Those are tricky bugs to fix.
By the way, this is probably a good point to return the properties to weak:
@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet UISearchBar *searchBar;
For ARC-enabled apps the Enable Zombie Objects setting (also known as NSZombieEnabled) isn’t terribly useful anymore, so you can disable it… except when you’re using unsafe_unretained pointers!
If it is so harmful then why use unsafe_unretained in the first place? A big reason is iOS 4.
Using ARC on iOS 4
Because ARC is largely a new feature of the LLVM 3.0 compiler and not of iOS 5, you can also use it on iOS 4.0 and up. The only part of ARC that does require iOS 5 are the weak pointers. That means if you wish to deploy your ARC app on iOS 4, you cannot use weak properties or __weak variables.
You don’t need to do anything special to make your ARC project work on iOS 4. If you choose a version of iOS 4 as your Deployment Target, then the compiler will automatically insert a compatibility library into your project that makes the ARC functionality available on iOS 4. That’s it, just pick iOS 4.x as the Deployment Target and you’re done.
If you use weak references anywhere in your code, the compiler will give the following error:
"Error: the current deployment target does not support automated __weak references"
You cannot use weak or __weak on iOS 4, so replace weak properties with unsafe_unretained and __weak variables with __unsafe_unretrained. Remember that these variables aren’t set to nil when the referenced object is deallocated, so if you’re not careful your variables may be pointing at objects that no longer exist. Be sure to test your app with NSZombieEnabled!
Where To Go From Here?
Here is an example project with all of the code from the above tutorial.
Congratulations, you’ve covered the basics of ARC and are ready to start using it in your own new apps – and you know how to port your old ones!
If you want to learn more about ARC, check out our book iOS 5 By Tutorials, where we have an additional chapter covering:
- Using blocks with ARC. The rules for using blocks have changed a little. You need to take special care to avoid ownership cycles, the only memory problem that even ARC cannot take care of automatically.
- How to make singletons with ARC. You can no longer override retain and release to ensure your singleton classes can have only one instance, so how do you make singletons work with ARC?
- More about autorelease. All about autorelease and the autorelease pool.
- Making games with ARC and Cocos2D. I’ll also explain how ARC fits in with Objective-C++, which you need to know if your game uses the Box2D physics engine.
- Static libraries. How to make your own static library to keep the ARC and non-ARC parts of your project separate.
If you have any questions or comments on this tutorial or ARC in iOS 5 in general, please join the forum discussion below!
This is a post by iOS Tutorial Team member Matthijs Hollemans, an experienced iOS developer and designer.