I am developing exclusively for iOS 5 using ARC. Should IBOutlets to UIViews (and subclasses) be strong or weak?
The following:
#property (nonatomic, weak) IBOutlet UIButton *button;
Would get rid of all of this:
- (void)viewDidUnload
{
// ...
self.button = nil;
// ...
}
Are there any problems doing this? The templates are using strong as are the automatically generated properties created when connecting directly to the header from the 'Interface Builder' editor, but why? The UIViewController already has a strong reference to its view which retains its subviews.
WARNING, OUTDATED ANSWER: this answer is not up to date as per WWDC 2015, for the correct answer refer to the accepted answer (Daniel Hall) above. This answer will stay for record.
Summarized from the developer library:
From a practical perspective, in iOS and OS X outlets should be defined as declared properties. Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create will therefore typically be weak by default, because:
Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary references between objects that do not imply ownership.
The strong outlets are frequently specified by framework classes (for example, UIViewController’s view outlet, or NSWindowController’s window outlet).
#property (weak) IBOutlet MyView *viewContainerSubview;
#property (strong) IBOutlet MyOtherClass *topLevelObject;
The current recommended best practice from Apple is for IBOutlets to be strong unless weak is specifically needed to avoid a retain cycle. As Johannes mentioned above, this was commented on in the "Implementing UI Designs in Interface Builder" session from WWDC 2015 where an Apple Engineer said:
And the last option I want to point out is the storage type, which can
either be strong or weak. In general you should make your outlet
strong, especially if you are connecting an outlet to a subview or to
a constraint that's not always going to be retained by the view
hierarchy. The only time you really need to make an outlet weak is if
you have a custom view that references something back up the view
hierarchy and in general that's not recommended.
I asked about this on Twitter to an engineer on the IB team and he confirmed that strong should be the default and that the developer docs are being updated.
https://twitter.com/_danielhall/status/620716996326350848
https://twitter.com/_danielhall/status/620717252216623104
While the documentation recommends using weak on properties for subviews, since iOS 6 it seems to be fine to use strong (the default ownership qualifier) instead. That's caused by the change in UIViewController that views are not unloaded anymore.
Before iOS 6, if you kept strong links to subviews of the controller's view around, if the view controller's main view got unloaded, those would hold onto the subviews as long as the view controller is around.
Since iOS 6, views are not unloaded anymore, but loaded once and then stick around as long as their controller is there. So strong properties won't matter. They also won't create strong reference cycles, since they point down the strong reference graph.
That said, I am torn between using
#property (nonatomic, weak) IBOutlet UIButton *button;
and
#property (nonatomic) IBOutlet UIButton *button;
in iOS 6 and after:
Using weak clearly states that the controller doesn't want ownership of the button.
But omitting weak doesn't hurt in iOS 6 without view unloading, and is shorter. Some may point out that is also faster, but I have yet to encounter an app that is too slow because of weak IBOutlets.
Not using weak may be perceived as an error.
Bottom line: Since iOS 6 we can't get this wrong anymore as long as we don't use view unloading. Time to party. ;)
I don't see any problem with that. Pre-ARC, I've always made my IBOutlets assign, as they're already retained by their superviews. If you make them weak, you shouldn't have to nil them out in viewDidUnload, as you point out.
One caveat: You can support iOS 4.x in an ARC project, but if you do, you can't use weak, so you'd have to make them assign, in which case you'd still want to nil the reference in viewDidUnload to avoid a dangling pointer. Here's an example of a dangling pointer bug I've experienced:
A UIViewController has a UITextField for zip code. It uses CLLocationManager to reverse geocode the user's location and set the zip code. Here's the delegate callback:
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
Class geocoderClass = NSClassFromString(#"CLGeocoder");
if (geocoderClass && IsEmpty(self.zip.text)) {
id geocoder = [[geocoderClass alloc] init];
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (self.zip && IsEmpty(self.zip.text)) {
self.zip.text = [[placemarks objectAtIndex:0] postalCode];
}
}];
}
[self.locationManager stopUpdatingLocation];
}
I found that if I dismissed this view at the right time and didn't nil self.zip in viewDidUnload, the delegate callback could throw a bad access exception on self.zip.text.
IBOutlet should be strong, for performance reason. See Storyboard Reference, Strong IBOutlet, Scene Dock in iOS 9
As explained in this paragraph, the outlets to subviews of the view
controller’s view can be weak, because these subviews are already
owned by the top-level object of the nib file. However, when an Outlet
is defined as a weak pointer and the pointer is set, ARC calls the
runtime function:
id objc_storeWeak(id *object, id value);
This adds the pointer
(object) to a table using the object value as a key. This table is
referred to as the weak table. ARC uses this table to store all the
weak pointers of your application. Now, when the object value is
deallocated, ARC will iterate over the weak table and set the weak
reference to nil. Alternatively, ARC can call:
void objc_destroyWeak(id * object)
Then, the object is
unregistered and objc_destroyWeak calls again:
objc_storeWeak(id *object, nil)
This book-keeping associated
with a weak reference can take 2–3 times longer over the release of a
strong reference. So, a weak reference introduces an overhead for the
runtime that you can avoid by simply defining outlets as strong.
As of Xcode 7, it suggests strong
If you watch WWDC 2015 session 407 Implementing UI Designs in Interface Builder, it suggests (transcript from http://asciiwwdc.com/2015/sessions/407)
And the last option I want to point out is the storage type, which can either be strong or weak.
In general you should make your outlet strong, especially if you are connecting an outlet to a sub view or to a constraint that's not always going to be retained by the view hierarchy.
The only time you really need to make an outlet weak is if you have a custom view that references something back up the view hierarchy and in general that's not recommended.
So I'm going to choose strong and I will click connect which will generate my outlet.
In iOS development NIB loading is a little bit different from Mac development.
In Mac development an IBOutlet is usually a weak reference: if you have a subclass of NSViewController only the top-level view will be retained and when you dealloc the controller all its subviews and outlets are freed automatically.
UiViewController use Key Value Coding to set the outlets using strong references. So when you dealloc your UIViewController, the top view will automatically deallocated, but you must also deallocate all its outlets in the dealloc method.
In this post from the Big Nerd Ranch, they cover this topic and also explain why using a strong reference in IBOutlet is not a good choice (even if it is recommended by Apple in this case).
One thing I wish to point out here, and that is, despite what the Apple engineers have stated in their own WWDC 2015 video here:
https://developer.apple.com/videos/play/wwdc2015/407/
Apple keeps changing their mind on the subject, which tells us that there is no single right answer to this question. To show that even Apple engineers are split on this subject, take a look at Apple's most recent
sample code, and you'll see some people use weak, and some don't.
This Apple Pay example uses weak:
https://developer.apple.com/library/ios/samplecode/Emporium/Listings/Emporium_ProductTableViewController_swift.html#//apple_ref/doc/uid/TP40016175-Emporium_ProductTableViewController_swift-DontLinkElementID_8
As does this picture-in-picture example:
https://developer.apple.com/library/ios/samplecode/AVFoundationPiPPlayer/Listings/AVFoundationPiPPlayer_PlayerViewController_swift.html#//apple_ref/doc/uid/TP40016166-AVFoundationPiPPlayer_PlayerViewController_swift-DontLinkElementID_4
As does the Lister example:
https://developer.apple.com/library/ios/samplecode/Lister/Listings/Lister_ListCell_swift.html#//apple_ref/doc/uid/TP40014701-Lister_ListCell_swift-DontLinkElementID_57
As does the Core Location example:
https://developer.apple.com/library/ios/samplecode/PotLoc/Listings/Potloc_PotlocViewController_swift.html#//apple_ref/doc/uid/TP40016176-Potloc_PotlocViewController_swift-DontLinkElementID_6
As does the view controller previewing example:
https://developer.apple.com/library/ios/samplecode/ViewControllerPreviews/Listings/Projects_PreviewUsingDelegate_PreviewUsingDelegate_DetailViewController_swift.html#//apple_ref/doc/uid/TP40016546-Projects_PreviewUsingDelegate_PreviewUsingDelegate_DetailViewController_swift-DontLinkElementID_5
As does the HomeKit example:
https://developer.apple.com/library/ios/samplecode/HomeKitCatalog/Listings/HMCatalog_Homes_Action_Sets_ActionSetViewController_swift.html#//apple_ref/doc/uid/TP40015048-HMCatalog_Homes_Action_Sets_ActionSetViewController_swift-DontLinkElementID_23
All those are fully updated for iOS 9, and all use weak outlets. From this we learn that A. The issue is not as simple as some people make it out to be. B. Apple has changed their mind repeatedly, and C. You can use whatever makes you happy :)
Special thanks to Paul Hudson (author of www.hackingwithsift.com) who gave me the clarification, and references for this answer.
I hope this clarifies the subject a bit better!
Take care.
From WWDC 2015 there is a session on Implementing UI Designs in Interface Builder. Around the 32min mark he says that you always want to make your #IBOutlet strong.
Be aware, IBOutletCollection should be #property (strong, nonatomic).
It looks like something has changed over the years and now Apple recommends to use strong in general. The evidence on their WWDC session is in session 407 - Implementing UI Designs in Interface Builder and starts at 32:30. My note from what he says is (almost, if not exactly, quoting him):
outlet connections in general should be strong especially if we connect a subview or constraint that is not always retained by the
view hierarchy
weak outlet connection might be needed when creating custom views that has some reference to something back up in the view hierarchy
and in general it is not recommended
In other wards it should be always strong now as long as some of our custom view doesn't create a retain cycle with some of the view up in the view hierarchy
EDIT :
Some may ask the question. Does keeping it with a strong reference doesn't create a retain cycle as the root view controller and the owning view keeps the reference to it? Or why that changed happened?
I think the answer is earlier in this talk when they describe how the nibs are created from the xib. There is a separate nib created for a VC and for the view. I think this might be the reason why they change the recommendations. Still it would be nice to get a deeper explanation from Apple.
I think that most important information is:
Elements in xib are automatically in subviews of view. Subviews is NSArray. NSArray owns it's elements. etc have strong pointers on them. So in most cases you don't want to create another strong pointer (IBOutlet)
And with ARC you don't need to do anything in viewDidUnload
Related
I am developing exclusively for iOS 5 using ARC. Should IBOutlets to UIViews (and subclasses) be strong or weak?
The following:
#property (nonatomic, weak) IBOutlet UIButton *button;
Would get rid of all of this:
- (void)viewDidUnload
{
// ...
self.button = nil;
// ...
}
Are there any problems doing this? The templates are using strong as are the automatically generated properties created when connecting directly to the header from the 'Interface Builder' editor, but why? The UIViewController already has a strong reference to its view which retains its subviews.
WARNING, OUTDATED ANSWER: this answer is not up to date as per WWDC 2015, for the correct answer refer to the accepted answer (Daniel Hall) above. This answer will stay for record.
Summarized from the developer library:
From a practical perspective, in iOS and OS X outlets should be defined as declared properties. Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create will therefore typically be weak by default, because:
Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary references between objects that do not imply ownership.
The strong outlets are frequently specified by framework classes (for example, UIViewController’s view outlet, or NSWindowController’s window outlet).
#property (weak) IBOutlet MyView *viewContainerSubview;
#property (strong) IBOutlet MyOtherClass *topLevelObject;
The current recommended best practice from Apple is for IBOutlets to be strong unless weak is specifically needed to avoid a retain cycle. As Johannes mentioned above, this was commented on in the "Implementing UI Designs in Interface Builder" session from WWDC 2015 where an Apple Engineer said:
And the last option I want to point out is the storage type, which can
either be strong or weak. In general you should make your outlet
strong, especially if you are connecting an outlet to a subview or to
a constraint that's not always going to be retained by the view
hierarchy. The only time you really need to make an outlet weak is if
you have a custom view that references something back up the view
hierarchy and in general that's not recommended.
I asked about this on Twitter to an engineer on the IB team and he confirmed that strong should be the default and that the developer docs are being updated.
https://twitter.com/_danielhall/status/620716996326350848
https://twitter.com/_danielhall/status/620717252216623104
While the documentation recommends using weak on properties for subviews, since iOS 6 it seems to be fine to use strong (the default ownership qualifier) instead. That's caused by the change in UIViewController that views are not unloaded anymore.
Before iOS 6, if you kept strong links to subviews of the controller's view around, if the view controller's main view got unloaded, those would hold onto the subviews as long as the view controller is around.
Since iOS 6, views are not unloaded anymore, but loaded once and then stick around as long as their controller is there. So strong properties won't matter. They also won't create strong reference cycles, since they point down the strong reference graph.
That said, I am torn between using
#property (nonatomic, weak) IBOutlet UIButton *button;
and
#property (nonatomic) IBOutlet UIButton *button;
in iOS 6 and after:
Using weak clearly states that the controller doesn't want ownership of the button.
But omitting weak doesn't hurt in iOS 6 without view unloading, and is shorter. Some may point out that is also faster, but I have yet to encounter an app that is too slow because of weak IBOutlets.
Not using weak may be perceived as an error.
Bottom line: Since iOS 6 we can't get this wrong anymore as long as we don't use view unloading. Time to party. ;)
I don't see any problem with that. Pre-ARC, I've always made my IBOutlets assign, as they're already retained by their superviews. If you make them weak, you shouldn't have to nil them out in viewDidUnload, as you point out.
One caveat: You can support iOS 4.x in an ARC project, but if you do, you can't use weak, so you'd have to make them assign, in which case you'd still want to nil the reference in viewDidUnload to avoid a dangling pointer. Here's an example of a dangling pointer bug I've experienced:
A UIViewController has a UITextField for zip code. It uses CLLocationManager to reverse geocode the user's location and set the zip code. Here's the delegate callback:
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
Class geocoderClass = NSClassFromString(#"CLGeocoder");
if (geocoderClass && IsEmpty(self.zip.text)) {
id geocoder = [[geocoderClass alloc] init];
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (self.zip && IsEmpty(self.zip.text)) {
self.zip.text = [[placemarks objectAtIndex:0] postalCode];
}
}];
}
[self.locationManager stopUpdatingLocation];
}
I found that if I dismissed this view at the right time and didn't nil self.zip in viewDidUnload, the delegate callback could throw a bad access exception on self.zip.text.
IBOutlet should be strong, for performance reason. See Storyboard Reference, Strong IBOutlet, Scene Dock in iOS 9
As explained in this paragraph, the outlets to subviews of the view
controller’s view can be weak, because these subviews are already
owned by the top-level object of the nib file. However, when an Outlet
is defined as a weak pointer and the pointer is set, ARC calls the
runtime function:
id objc_storeWeak(id *object, id value);
This adds the pointer
(object) to a table using the object value as a key. This table is
referred to as the weak table. ARC uses this table to store all the
weak pointers of your application. Now, when the object value is
deallocated, ARC will iterate over the weak table and set the weak
reference to nil. Alternatively, ARC can call:
void objc_destroyWeak(id * object)
Then, the object is
unregistered and objc_destroyWeak calls again:
objc_storeWeak(id *object, nil)
This book-keeping associated
with a weak reference can take 2–3 times longer over the release of a
strong reference. So, a weak reference introduces an overhead for the
runtime that you can avoid by simply defining outlets as strong.
As of Xcode 7, it suggests strong
If you watch WWDC 2015 session 407 Implementing UI Designs in Interface Builder, it suggests (transcript from http://asciiwwdc.com/2015/sessions/407)
And the last option I want to point out is the storage type, which can either be strong or weak.
In general you should make your outlet strong, especially if you are connecting an outlet to a sub view or to a constraint that's not always going to be retained by the view hierarchy.
The only time you really need to make an outlet weak is if you have a custom view that references something back up the view hierarchy and in general that's not recommended.
So I'm going to choose strong and I will click connect which will generate my outlet.
In iOS development NIB loading is a little bit different from Mac development.
In Mac development an IBOutlet is usually a weak reference: if you have a subclass of NSViewController only the top-level view will be retained and when you dealloc the controller all its subviews and outlets are freed automatically.
UiViewController use Key Value Coding to set the outlets using strong references. So when you dealloc your UIViewController, the top view will automatically deallocated, but you must also deallocate all its outlets in the dealloc method.
In this post from the Big Nerd Ranch, they cover this topic and also explain why using a strong reference in IBOutlet is not a good choice (even if it is recommended by Apple in this case).
One thing I wish to point out here, and that is, despite what the Apple engineers have stated in their own WWDC 2015 video here:
https://developer.apple.com/videos/play/wwdc2015/407/
Apple keeps changing their mind on the subject, which tells us that there is no single right answer to this question. To show that even Apple engineers are split on this subject, take a look at Apple's most recent
sample code, and you'll see some people use weak, and some don't.
This Apple Pay example uses weak:
https://developer.apple.com/library/ios/samplecode/Emporium/Listings/Emporium_ProductTableViewController_swift.html#//apple_ref/doc/uid/TP40016175-Emporium_ProductTableViewController_swift-DontLinkElementID_8
As does this picture-in-picture example:
https://developer.apple.com/library/ios/samplecode/AVFoundationPiPPlayer/Listings/AVFoundationPiPPlayer_PlayerViewController_swift.html#//apple_ref/doc/uid/TP40016166-AVFoundationPiPPlayer_PlayerViewController_swift-DontLinkElementID_4
As does the Lister example:
https://developer.apple.com/library/ios/samplecode/Lister/Listings/Lister_ListCell_swift.html#//apple_ref/doc/uid/TP40014701-Lister_ListCell_swift-DontLinkElementID_57
As does the Core Location example:
https://developer.apple.com/library/ios/samplecode/PotLoc/Listings/Potloc_PotlocViewController_swift.html#//apple_ref/doc/uid/TP40016176-Potloc_PotlocViewController_swift-DontLinkElementID_6
As does the view controller previewing example:
https://developer.apple.com/library/ios/samplecode/ViewControllerPreviews/Listings/Projects_PreviewUsingDelegate_PreviewUsingDelegate_DetailViewController_swift.html#//apple_ref/doc/uid/TP40016546-Projects_PreviewUsingDelegate_PreviewUsingDelegate_DetailViewController_swift-DontLinkElementID_5
As does the HomeKit example:
https://developer.apple.com/library/ios/samplecode/HomeKitCatalog/Listings/HMCatalog_Homes_Action_Sets_ActionSetViewController_swift.html#//apple_ref/doc/uid/TP40015048-HMCatalog_Homes_Action_Sets_ActionSetViewController_swift-DontLinkElementID_23
All those are fully updated for iOS 9, and all use weak outlets. From this we learn that A. The issue is not as simple as some people make it out to be. B. Apple has changed their mind repeatedly, and C. You can use whatever makes you happy :)
Special thanks to Paul Hudson (author of www.hackingwithsift.com) who gave me the clarification, and references for this answer.
I hope this clarifies the subject a bit better!
Take care.
From WWDC 2015 there is a session on Implementing UI Designs in Interface Builder. Around the 32min mark he says that you always want to make your #IBOutlet strong.
Be aware, IBOutletCollection should be #property (strong, nonatomic).
It looks like something has changed over the years and now Apple recommends to use strong in general. The evidence on their WWDC session is in session 407 - Implementing UI Designs in Interface Builder and starts at 32:30. My note from what he says is (almost, if not exactly, quoting him):
outlet connections in general should be strong especially if we connect a subview or constraint that is not always retained by the
view hierarchy
weak outlet connection might be needed when creating custom views that has some reference to something back up in the view hierarchy
and in general it is not recommended
In other wards it should be always strong now as long as some of our custom view doesn't create a retain cycle with some of the view up in the view hierarchy
EDIT :
Some may ask the question. Does keeping it with a strong reference doesn't create a retain cycle as the root view controller and the owning view keeps the reference to it? Or why that changed happened?
I think the answer is earlier in this talk when they describe how the nibs are created from the xib. There is a separate nib created for a VC and for the view. I think this might be the reason why they change the recommendations. Still it would be nice to get a deeper explanation from Apple.
I think that most important information is:
Elements in xib are automatically in subviews of view. Subviews is NSArray. NSArray owns it's elements. etc have strong pointers on them. So in most cases you don't want to create another strong pointer (IBOutlet)
And with ARC you don't need to do anything in viewDidUnload
Hi I am a newbie to iOS programming. I know what a strong and weak reference is. But I get confused which type of reference to use when I have to deal with outlets. After going through the documentation which states that
Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong.
So what I understood after going through the above statement is that the Outlets that we create should typically be weak by default.
But while studying some tutorials I have come across the code where people have declared an outlet as strong reference. For example consider the following code :
#interface AboutViewController : UIViewController
#property (nonatomic, strong) IBOutlet UIWebView *webView;
#end
The code :
#property (nonatomic, strong) IBOutlet UIWebView *webView;
says that our AboutViewController has an UIWebView object.
But why we need a strong reference here for the UIView object?? As the document states shouldn't this be an weak reference ?
Also please explain in the documentation statement which I have quoted above what does the File’s Owner to top-level objects mean?.
I have gone through many of the similar questions on this website but none of them helped me to clear my doubt. So please help. Thanks in advance :)
What to use for non top level GUI elements - strong or weak - depends on how you are going to use their outlets. If you have a weak reference
#property (nonatomic, weak) IBOutlet UIWebView *webView;
then after calling method
[webView removeFromSupeview];
your webView will be nil and it will be impossible to restore UIWebView just by adding
[self.view addSubview:webView];
If this is appropriate for you - it is better to use weak because you will free webView's memory when you do not need it.
On the other hand, in case of a strong reference after
[webView removeFromSupeview];
webView will still have referenceCount > 0 and webView will be deallocated only if owner will free it explicitly
self.webView = nil;
or in the owner's
- (void)dealloc
together with the owner itself.
Usually there is no difference if you have static GUI. If you want to remove (not hide) some views add be able to add them later - strong references should be used.
Top level objects should be retained strong. Like
#property(nonatomic,retain) UIView *view;
in UIViewController.
It usually doesn't hurt to use a strong reference in place of a weak one in the case of outlets like this. And in some cases, you do need a strong reference.
The idea is that something has to keep a strong reference to the object at all times or it could vanish. If the object is a view that is a subview of another view, then that superview will keep a strong reference to it and so you can use a weak reference. But, if you're going to do something else with that view, such as remove it from it's superview for some reason (maybe to reuse it elsewhere, or something), then you'll want to use a strong property so that there's always something holding it strongly.
Regarding the File Owner issue, that's because the top level object (most likely a view) does not have a superview holding on to it, so you need to use a strong property so that you're holding on to it.
The simple answer is that unless you are supporting iOS 5, outlets should always be strong.
The purpose of weak outlets was so that in iOS5, if the system unloaded the view controller's view to save memory, any outlets pointing to subviews would be automatically released.
In iOS 6 and later, the system never unloads the view controller's view (viewDidUnload is never called) because Apple found a way to release most of the memory used by a view without releasing the view itself.
Consequently, the outlets in a view controller will never normally need to be released until the view controller itself is released, at which point ARC will clean up all the outlets anyway.
So just use strong for all your outlets and you won't have to worry about obscure bugs or compiler warnings due to using the wrong reference type.
Quoting from Apple's Resource Programming Guide,
Each time you ask the NSBundle or NSNib class to load a nib file, the underlying code creates a new copy of the objects in that file and returns them to you. You need to ensure that you maintain the new object graph as long as necessary, and disown it when you are finished with it. You typically need strong references to top-level objects to ensure that they are not deallocated; you don’t need strong references to objects lower down in the graph because they’re owned by their parents, and you should minimize the risk of creating strong reference cycles.
In case of framework classes like UIViewController the top-level object for the NIB file is the view property. If you check in the documentation it is declared as retain(similar to strong).
#property(nonatomic, retain) UIView *view
So any subviews to this container view should be automatically owned by it. If you now declare these subview outlets as strong they will create a strong cycle and cause memory leaks when the framework tries to cleanup the container view. To avoid these strong cycles all subviews (or non top level objects) should be declared as weak properties.
When can you declare IBOutlet's as strong
Outlets should be changed to strong when the outlet should be considered to own the referenced object:
As indicated previously, this is often the case with File’s Owner—top level objects in a nib file are frequently considered to be owned by the File’s Owner.
You may in some situations need an object from a nib file to exist outside of its original container. For example, you might have an outlet for a view that can be temporarily removed from its initial view hierarchy and must therefore be maintained independently.
You need to check in your code if webView object qualifies for case2 as above. If not the tutorial has got this one wrong and it actually should be weak.
Hope that helps!
An application that I am working on, that uses ARC and needs to support iOS 4.3 and iOS 5, declares every outlet as #property (strong, nonatomic) IBOutlet in the .h file.
e.g.
// myClass.h
#property (strong, nonatomic) IBOutlet UITextView *myTextview;
I know that with ARC only properties which do not hold a strong reference to an object are released.
As a result, the App relies on - (void)viewDidUnload to set the property myTextview to nil.
i.e.
// myClass.m
- (void)viewDidUnload
{
[super viewDidUnload];
self.myTextview = nil;
}
I know, from Apple's Documentation, that Outlets should generally be weak except those from File's Owner ( i.e. A Runtime Object that owns the contents of the iOS Storyboard scene) to Top-Level Objects (my rule of thumb is to use anything that appears in the window with File's Owner, First Responder and View).
Anything I add to the view will be a subview and thus is retained by it's direct superview, meaning a weak reference should be used.
I am also aware that - (void)viewDidUnload is deprecated in iOS 6 and is not called.
1st Question : What are the issues with taking the approach of declaring every outlet as a strong property and setting it to nil in viewDidUnload, apart from the fact that viewDidUnload is deprecated in iOS 6?
My intuition tells me that it is because situations arise where you can set a pointer to nil, before viewDidUnload is called. So you should, to free up memory on the heap. Is there a noticable performance change if this is the case?
2nd Question : Should I go back throughout the project and change strong to weak? Why? Is it worth the time?
3rd Question : If I was to declare the property in a class extension, to 'hide' it, how does this affect my rule of thumb for deciding on when to use strong or weak.
I know there are many threads here that discuss this issue. But many I've found are out of date, and do not address this issue directly. Thanks.
First, a few of your presumptions need addressing:
I know that ARC only releases properties which do not hold a strong
reference to an object. As a result, the App relies on -
(void)viewDidUnload to set the property myTextview to nil.
Not quite. ARC never retained weak properties in the first place. As for strong properties, ARC still releases them, but not until dealloc is called.
viewDidUnload was never used to prevent leaks. It was essentially an optimization, and one that Apple decided was no longer worth the trouble. To understand, consider the standard lifecycle of a pre-iOS6 view controller:
1. Allocated
2a. View Loaded
2b. View Unloaded
3. Deallocated
Where 2a and 2b could be repeated any number of times. For example, a view controller at the bottom of a navigation stack (its view being hidden) could have its view unloaded in low memory situations. It would then be reloaded the next its view became visible.
The method was essentially saying "Hey view controller programmer, we're running low on memory, and nobody can see me anyways, so I'm releasing my view. If you could do the same for your strong properties, that would be great."
That process had subtleties and was generally confusing. As a result of the tediousness, Apple deprecated it. Views are no longer unloaded, so there's no point in implementing it. The key point is that all your strong properties will still be released in ARC's dealloc method.
I know that Outlets should generally be weak...
Why do you know that? There's nothing special about outlets. The 'IBOutlet' keyword is really just for Xcode's benefit when designing things with its visual tools. It has no effect on the compiled code. So, when thinking about strong vs weak outlets, use the same considerations that you do for any other property, namely "do I need this to exists, or am I okay with it disappearing on me?".
What are the issues with taking the approach of
declaring every outlet as a strong property and setting it to nil in
viewDidUnload, apart from the fact that viewDidUnload is deprecated in
iOS 6?
There are no issues with that. If you want your properties to exists as long as your controller, then use strong. viewDidUnload has nothing to do with this. On older iOS versions, you could release strong outlets in viewDidUnload if you want.
Should I go back throughout the project and change
strong to weak? Why? Is it worth the time?
Again, just use whichever qualifier makes sense for your use case. You're almost always safe using strong for you outlets.
If I was to declare the property in a class extension, to 'hide' it,
how does this affect my rule of thumb for deciding on when to use
strong or weak.
There's no difference.
1st question: The outlets are subviews of the main view which is a property of the view controller. If you declare them as weak, they have a retain count of 1, since they are subviews. If the view is released, they are also released. If you declare them as strong, they have a retain count of 2, since they are subviews, and strong properties of the view controller. So they are only released when the view controller is released (which releases also its view and its subviews). To my understanding, the difference is that when the view of a view controller is released, e.g. when it is not presented and memory is low, the outlets still allocate memory when they have been declared as strong.
2nd question: I believe in most circumstances it does not matter.
3rd question: I believe if you declare properties in a class extension, the simply belong to the class, and thus there is no difference in handling them compared to "real" class properties.
My approach would be to make sure not to declare properties as strong that could result in retain cycles, what happens, i.e., if you declare a delegate as strong.
I am developing an iPhone app with ARC option enabled. i am creating IBOutlets in .h files which are connected from file owners icon to .xib elements.for eg.
IBOutlet UIButton *bt;
#property(nonatomic,retain)IBOutlet UIButton *bt;
in .m file, i am doing
#synthesize bt;
Is there a need to explicitly set bt to nil in viewDidUnload method? i.e. self.bt = nil; in viewDidUnload?
Also, do I need to write dealloc method with ARC option enabled? When should I make IBOutlets elements as strong and weak references with ARC enabled?
There's a difference between the need to put your outlets to nil in viewDidUnload and dealloc
Having ARC means you don't need to write that in your dealloc method (it gets done automatically), however the viewDidUnload method serves another purpose, and it is to free memory that the application isn't using when a memory warning occurs.
dealloc is still needed in some cases, for example, when your class is registered for a notification, or when your class is someone else's delegate and you don't want some glitchy callback giving you a bad access
When you get a memory warning, all the UIViewControllers not being displayed will unload their view and call that method to free up memory. If you are still retaining outlets (like buttons, tables and etc) they will not get released, thus, killing the purpose of the viewDidUnload method.
When using ARC there is no need to use modifiers like retain or copy, for example. That kind of memory managment is done automatically using the strong and weak modifiers.
You also don't have to worry about writing dealloc methods.
strong is kind of the equivalent of retain, so you should mark your outlets with it
#property(nonatomic, strong) IBOutlet UIButton *bt;
That's the way interface builder creates them by default.
I won't go into detail about their semantic differences, but you should really have a look at Apple's guide on transitioning to ARC if you want to know what's going on and read about the specifics of strong and weak modifiers.
EDIT:
Sorry, interface builder creates outlets with weak by default.
EDIT 2:
strong and retain are indeed 100% identical. (thanks to #Adam)
EDIT 3:
You set your pointers to nil to avoid getting any message sent to deallocated instance or BAD_ACCESS_EXCEPTION errors.
If you are actually using ARC, you should make your outlets (nonatomic, weak) instead of (nonatomic, strong). By using the weak zeroing pointers, what the compiler does is automatically set your outlets to nil when nothing else references them.
So, summing up, if you don't use weak properties, you should set your pointers to nil.
I'm still learning iOS development and have been working with various tutorials and books. Some pre-ARC, some with ARC.
In some cases, we're taught to release all of the properties and subviews of a ViewController on viewDidUnload but in some cases I've been told this is no longer required.
Can someone give a definitive answer? In iOS 5+, does one have to do the whole:
-(void)viewDidUnload
{
[super viewDidUnload];
self.photoViewCell = nil;
self.photoImageView = nil;
self.firstNameTextField = nil;
self.lastNameTextField = nil;
}
... or not? If so, is this only for properties that are descendants of UIView or is it for all properties of the ViewController?
Thanks
So each view has a number of owners. When that "owner count" (usually referred to as the retainCount) reaches 0, that object gets destroyed.
In iOS 5, we now have weak references, which essentially means "don't own this object".
Before iOS 5, in our header files, you'd see
IBOutlet UILabel *myLabel;
And this label was added to the XIB file's view. myLabel has 2 owners in this case: it's superview (the view in the XIB file) and the view controller (by having the IBOutlet). When viewDidUnload get's called, the view controller's view has been released, and therefore it's ownership of myLabel is gone. So myLabel at this point only has 1 owner, the view controller. So we needed to release it in viewDidLoad to make sure it didn't have any owners and so was destroyed.
With iOS 5, you will often seen this instead
__weak IBOutlet UILabel *myLabel
This is saying that we don't want the view controller to be an owner of myLabel. So the only owner is the view controller's view. So when viewDidUnload get's called, the view controller's view has already been released, and so its ownership of myLabel has also been released. In this case, myLabel now has no owners and its memory is released. There is no need for the self.myLabel = nil; there.
So with iOS 5, the recommendation is to make all of your IBOutlets a weak reference. With this, you don't even need to implement viewDidUnload, as all the memory has been taken care of for you.
But even if you are using iOS 5, if your IBOutlets aren't weak references, you'll need that code in viewDidUnload.
viewDidUnload has nothing to do with retain counting, automatic or otherwise. This method will be called when a view is unloaded due to memory pressure, which means that you should also nil (and release, non-ARC) elements of the view that you hold strong references to. Failure to do this may mean that your app does not free enough memory when under memory pressure, which can lead to it being closed by the OS.
You can use viewDidUnload to manage Memory, if your App deserves it.
But don't do a
myInstanceVariable = nil;
You loose your reference to the memory location, where the values of your variable live.
= nil doesn't free the memory. Still, your object has to be deallocated. And therefore the retainCount and retain/release are used.
If you nil your object in viewDidUnload you cannot release in dealloc! Attention!!!
If you know, what you do, you can release and nil your object in viewDidUnload.
ARC:
Using ARC, you must not release manually, even I think you can't do so. ARC takes care of that.
Simply use #properties as much as you can with with (weak/strong) attribute to let getters and setters do the work for you. You can declare #properties in your .m file either (like in a class extension).
Simple rule: strong for objects you want to own, weak for objects, you don't want to get lost in a retain cycle and hold ownership to. ARC does the rest in almost all situations. Use weak for delegates for example.
nil objects, where you are sure, you won't send them a message to, otherwise do not.