I found something that I can't understand in UICollectionView header file. I found that the delegate has an assign property
#property (nonatomic, assign) id <UICollectionViewDelegate> delegate;
This question is only for my basic understanding as the rule says the delegate should have a weak property. And according to my personal knowledge, assign won't reference count the delegate object but it will surely still have a reference to a garbage value if the object is deallocated.
How can I understand this piece of code?
strong and weak were introduced alongside Automatic Reference Counting (ARC). UIKit moved to ARC with iOS 9, and if you look at the iOS 9 header (using Xcode 7) you will see that this property is now weak.
You are right: with the property as assign (which is equivalent to unsafe_unretained), if the delegate is deallocated while the collection view is alive, the collection view’s delegate property will point to where the deallocated object used to be and probably cause a crash when it is referenced. This is not usually a problem because the delegate is often the view controller owning the collection view so usually outlives the view. However, this is not a guarantee, which is why you should set assign delegates that point to you to nil in your dealloc.
Relevant Stack Overflow questions:
Objective-C ARC: strong vs retain and weak vs assign
Set delegates to nil under ARC?
ARC delegate memory management
Related
I can't understand why it is correct to define a delegate with weak pointer :
#property (nonatomic,weak) id delegate;
I can't realize why isn't necessary to retain a reference to the delegate... i don't want the object that i use as the delegate to be deallocated... thus, i would prefer using a strong reference not a weak!
In many cases the delegate is the same object where the instance of my class will be created, in this case creating a weak reference would be a great solution to avoid retain cycle... but what if I choose a totally different object as the delegate ?
I searched for other questions on stack overflow but I can't find something that can help me to fully understand this situation.
The reason that objects weakly retain their delegates is to avoid retain cycles. Imagine the following scenario: object a creates b and retains it, then sets itself as b's delegate. a is released by its owner, leaving a retain cycle containing a and b. This is actually a very common scenario. Consider a view controller that owns a view and acts as that view's delegate. In this case, the view should not retain the controller—as a mater of proper MVC architecture and to prevent retain cycles.
Though retain cycles are a valid concern, the reasoning for a weak reference is more related to apple's perspective on how to use the delegation pattern with uikit and other elements out of the box which is explained here:
http://developer.apple.com/library/IOs/documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html
Specifically:
"The main value of delegation is that it allows you to easily customize the behavior of several objects in one central object."
If the delegate deals with managing the delegated tasks of several objects then those objects need not retain the delegate and should not bear the responsibility of dealllocating the delegate as it might be used by other objects. The weak reference enforces the concept that the management of the delegate is not the delegators responsibility.
An example in objective c is a one delegate being used for multiple table views, like when using a table view and a searchdisplaycontroller with a uisearchbar. Apples examples use the controller as the delegate, but reasoning still holds when using one custom delegate for both the main table view and the results table view for your search. That custom delegate would likely be retained by your controller in order to be provided to both table views.
This is fundamentally different from the basic delegation pattern that is referred to in other languages where the delegate is often created by the delegator and each instance may manage a its own delegate instance.
This is to avoid retain cycles. Apple offers an informative guide on advanced memory management explaining the situation and how best to deal with it. In ARC, they are now known as strong reference cycles, which are explained in the Transitioning to ARC Release Notes.
Previously you would define a property for a delegate like this,
#property (nonatomic, assign) id delegate;
But in ARC, you can define it thus,
#property (nonatomic, unsafe_unretained) id delegate;
Or, for example, if you have a protocol named <MyObjectDelegate>, you can also define the delegate in this way,
#property (nonatomic, weak) id <MyObjectDelegate> delegate;
In other words, in ARC if you have a protocol, you can declare a delegate weak. Otherwise, unsafe_unretained.
As a common practice, if we have two objects holding references with each other, we make the "child" object in a "parent-children" relationship a weak reference.
For delegation patters in iOS, the delegated object is the parent, because there is no need for the delegate caller to exist without the delegated object. For example, you have a sentence object with delegate object for method sentenceShouldEnd. Your paragraph object is the delegated object for your sentence object. Obviously the paragraph object is actually the parent, and in your sentence object you should keep your delegate as a weak reference.
To your point you assign the delegate to self, your understanding is wrong. We should never assign delegate to itself. Why you buy your ticket yourself if you feel it is necessary to hire an agent to buy the ticket for you? You are saying two completely different concepts. When you define a delegate object as property, it's used a weak reference in the object it is defined in(lets say A, i.e. the delegate object is a property of A). The delegate is assigned when you init A(let's say in B), then most likely you would assign A.delegate to self, which is acturally B. You see the parent-child relationship here?? You alloc memory for A in B. You hold A in B. A does not exist without B. You are not assigning the delegate to A!!!!
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!
Have an interesting issue where there is a class that is referenced in an XIB layout (subclass of UIScrollView) and is not being de-allocated according to Instruments / Allocations and does not break in it's dealloc routine. Let's call it Sclass1.
There is a using class (let's call it Uclass) that has the XIB file and the outlet.
#property (nonatomic, weak) IBOutlet Sclass1* sclass1;
This is hooked properly to the XIB file layout.
Sclass1 is property allocated when the XIB for Uclass is loaded. Uclass does get deallocated and then recreated from time to time and thus we have another instance of Sclass1, but Sclass1 never goes away and can't find another reference to it.
Drill down in Instruments shows the one Malloc and that is it.
fyi, the class gets started with
[UIClassSwapper initWithCoder:]
If an object doesn't get deallocated under ARC, it means a strong reference to it exists. Since your property is weak the object must be owned strongly by something other than the Uclass object (Otherwise it would get deallocated immediately after the XIB has loaded). In the code you've provided it isn't clear what the actual strong owner of this object is, but I assume it could be one (or more) of the following:
Since the object's class is a UIView subclass, it may be (strongly) referenced by its superview if added as one of subviews. This happens automatically when a XIB file is loaded. If the superview doesn't get deallocated neither will the SClass object. You can remove this ownership by calling removeFromSuperview
A strong ownership cycle (retain-cycle) exists somewhere among ivars of the SClass1 object (i.e. one of the strongly-owned instance variables have a strong reference back to its owner - the SClass1). Beware that any block using self directly also keeps a strong reference. Having a strong reference to the block then often leads to a retain-cycle. Save self to a __weak var and pass that to the block instead unless you have a good reason not to.
A manually created strong reference exists by e.g. adding the object to a container or saving the pointer to a non-__weak variable.
Try finding and removing these strong ownerships. Only after all of them are removed the object can be deallocated.
Since your property is weak and it's still not deallocated, look for strong references to Sclass or it's owner, Uclass. Maybe you are using Uclass(or Sclass) in block directly, without __weak typeof(self) weakSelf dancing and this block creates retain cycle. Also watch for parent-child relations and delegates. Maybe there is delegate which is strong instead of weak or two controllers hold strong references to eachother.
Also, if you want to have more detailed answers, please post more relevant code.
I think your #property should be strong for a class :
#property (nonatomic, strong) IBOutlet Sclass1* sclass1;
Because strong is the equivalent to retain and ARC will manage the release for you.
You will have more information with the Apple Documentation about Transitioning to ARC Release Notes in the section on property attributes.
I recently had the same symptoms - To solve it in my case, my object was acting as delegate for a number of other objects, so had to release the object from all its delegate responsibilities before it would call dealloc
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.