I have switched my project to ARC, and I don't understand if I have to use strong
or weak
for IBOutlets. Xcode do this: in interface builder, if a create a UILabel
for example and I connect it with assistant editor to my ViewController
, it create this:
@property (nonatomic, strong) UILabel *aLabel;
It uses the strong
, instead I read a tutorial on RayWenderlich website that say this:
But for these two particular properties I have other plans. Instead of
strong
, we will declare them asweak
.
@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet UISearchBar *searchBar;
Weak
is the recommended relationship for all outlet properties. These view objects are already part of the view controller’s view hierarchy and don’t need to be retained elsewhere. The big advantage of declaring your outletsweak
is that it saves you time writing the viewDidUnload method.Currently our
viewDidUnload
looks like this:
- (void)viewDidUnload
{
[super viewDidUnload];
self.tableView = nil;
self.searchBar = nil;
soundEffect = nil;
}
You can now simplify it to the following:
- (void)viewDidUnload
{
[super viewDidUnload];
soundEffect = nil;
}
So use weak
, instead of the strong
, and remove the set to nil in the videDidUnload
, instead Xcode use the strong
, and use the self... = nil
in the viewDidUnload
.
My question is: when do I have to use strong
, and when weak
?
I want also use for deployment target iOS 4, so when do I have to use the unsafe_unretain
? Anyone can help to explain me well with a small tutorial, when use strong
, weak
and unsafe_unretain
with ARC?
A rule of thumb
When a parent has a reference to a child object, you should use a strong
reference. When a child has a reference to its parent object, you should use a weak
reference or a unsafe_unretained
one (if the former is not available). A typical scenario is when you deal with delegates. For example, a UITableViewDelegate
doesn't retain a controller class that contains a table view.
Here a simple schema to present the main concepts.
Suppose first A,B and C are strong
references. In particular, C has a strong
ref to its parent. When obj1 is released (somewhere), the A reference doesn't exist anymore but you have a leak since there is a cycle between obj1 and obj2. Speaking in terms of retain counts (only for explain purposes), obj1 has a retain count of 2 (obj2 has a strong
reference to it), while obj2 has a retain count of 1. If obj1 is released, its retain count is now 1 and its dealloc
method is not called. obj1 and obj2 still remain in memory but no one has a reference to them: Leak.
On the contary, if only A and B are strong
refs and C is qualified as weak
all is ok. You have no leaks. In fact, when obj1 is released, it also releases obj2. Speaking in terms of retain counts, obj1 has a retain count of 1, obj2 has a retain count of 1. If obj1 is released, its retain count is now 0 and its dealloc
method is called. obj1 and obj2 are removed from memory.
A simple suggestion: Start to think in terms of object graph when you deal with ARC.
About your first question, both solutions are valid when you deal with XIBs. In general weak
references are used when you deal with memory cycles.
Concerning XIBs files, if you use strong
you need to set nil
in viewDidUnload
since if you don't do it, in memory low conditions, you could cause unexpected leaks. You don't release them in dealloc
because ARC will do it for you.
weak
instead doesn't need that treatment since, when the target object is destroyed, those values are set as nil
automatically. No dangling pointers anymore.
If you are interested in, I really suggest you to read friday-qa-2012-04-13-nib-memory-management by Mike Ash.
About your second question, if you need to support iOS 4, instead of weak
you have to use unsafe_unretained
.
Within SO there are a lot of questions/answers. Here the main ones:
How do I replace weak references when using ARC and targeting iOS 4.0?
What kind of leaks does automatic reference counting in Objective-C not prevent or minimize?
using ARC, lifetime qualifier assign and unsafe_unretained
strong / weak / retain / unsafe_unretained / assign
Hope that helps.
Update
As per shaunlim's comment, starting from iOS 6 viewDidUnload
method is deprecated. Here I really suggest to see Rob's answer: iOS 6 - viewDidUnload migrate to didReceiveMemoryWarning?.