weak IBOutlet UIView property would become nil - ios

I have two UIViews in the nib file and I set them to be properties of my view controller, using the IBOutlet and weak keyword.
However, when I use self.view1 which I want to use to point to the view in the nib, for the first time, it works. But when I use it later, these two properties turn to be nil.
Using the strong property would fix the issue. But I always use weak for the IBOutlet property. Why it becomes nil in this situation?

You need to have a strong reference to top level items in a nib file. If you have two views at the top level of your nib, then you should have strong references to them, not weak ones.
Any subviews of these top level views can be made IBOutlets with weak references, because the top level view keeps a strong reference to these subviews, so you don't have to.
Most times, weak is good enough, because there is an implicit strong reference to the top level object. For Example, if you have a nib for a view controller, then the view controller object maintains a strong reference to the top level view because of it's view property, which means that you can have a weak hold on any other objects.

Related

When to create an outlet of strong type?

When we create an outlet its property is directly set to a weak type. However weak type contains on optional value. I want outlet created to be of strong type so that it always contains a value. But there is memory management issues and can form strong reference cycles.
Is there any kind of situation where i need to create an outlet of strong type?
Imagine you have created a subclass of UIView and named it ViewA. Now you are going to create ViewA by means of XIB or storyboard. All the subviews which you are going to add directly inside the ViewA will become weak property as ViewA will own them and will manage memory allocations by itself of its subview.
But now, if you want to create a ViewB inside the same XIB file where you already have ViewA as file owner and this ViewB is not going to be subview of ViewA, then while creating outlet of ViewB, it is to be noted that it becomes a strong outlet.
So in short, only the top level objects inside XIB or storyboard becomes strong reference whereas all the subviews inside these top level objects, they become weak reference.
You can read more about it in this Apple documentation
Edit: By creating a ViewB, I meant you drag and drop a UIView into the XIB editor, but not as a subview of already existing ViewA. You create it as an separate object. I have attached a screenshot for understanding. So, in this example, outlets of Button 1, Label 1 and Label 2 will be weak. Whereas outlets of ViewA and ViewB will be strong.
Generally, outlets only need to be strong if you might remove them from the superview at some point and potentially readd. If they were weak they would go to nil immediately after removing them. You could keep them as weak and just capture them strongly before removing them, but declaring them strong allows you skip that step.

IBOutlet why always weak and object of array ,dictionary etc are need to be strong

i am new in ios programming , i just want to know why we use IBoutlet of every controller to be weak and other Need to strong
can we define IBoutlet to be strong ?
if yes then what is difference ?
It has to do with ownership of the variable, since most IBOutlets are sub views of you view the ownership of the view lies with the view.
If you are creating your own properties you will need to retain the variable thus you make the property strong.

Weak references and Retain cycles

I'm developing an application that using ARC,so I have 3 cases:
1 #property (strong, nonatomic) IBOutlet UILabel *titleLabel;
That means: titleLable has a strong references to superView and superView has a strong references to titleLabel?
2 #property (weak, nonatomic) IBOutlet UILabel *titleLabel;
That means: titleLable has a weak references to superView and superView has a strong references to titleLabel?
3 I declare:
UILabel *titleLabel = [[UILabel alloc] initWithFrame:self.view.bounds];
[self.view addSubview:titleLabel]
Could everyone answer my questions?
My description for case 1 and 2 are correct?
In case 1, can the superView release or not? because i think titleLable has a strong reference to supperView
In case 3, why we dont need declare __weak for titleLabel, maybe superView can be release in this case?
Thanks for your responses.
The other answers here are good, but I want to be extra clear about a misconception you seem to have. Properties on classes are one-way relationships, not two.
So you ask in each case about how that property references its owner (strong or weak) but the reality is that it doesn't reference it at all. In fact no object has any knowledge of what other objects own it at any given time. The only thing that it tracks is how many objects own it. If you want a two way relationship where both objects have a reference to each other, that is when you need a weak reference in at least one direction. Otherwise, both object are making sure the other never gets dealloced and therefore neither will ever be dealloced. That is what is called a "circular reference". It can happen between more than two objects as well where A has a strong reference to B, B has a strong reference to C, and C has a strong reference to A.
Now, regarding the "superview" method on UIViews. This will always be a weak reference and is setup automatically when you add a subview. This is because the parent view always has a strong reference to all of its children. If a child ever had a strong reference to its parent, there would be a circular reference. But please note, that adding a property to a view, does not automatically add it as a subview, that must still be done manually in code or inside a xib or storyboard.
So in short, only case 3 creates reference between the view and the label because you added it as a subview. Then self.view has a strong reference to the label. As a completely different mechanism, the view then adds a weak reference to itself on the subview called "superview".
I'm going to assume titleLabel is a property in a UIViewController.
1.1 - UIViewController has a strong reference to titleLabel. titleLabel has no reference to UIViewController.
2.2 - UIViewController has a weak reference to titleLabel. titleLabel has no reference to UIViewController. titleLabel will only be retained if you have strong reference to it somewhere. Adding it to the view hierarchy counts as a strong reference.
3.3 - In this case UIViewController has a strong reference to titleLabel until it goes out of scope. However, you add it to the view hierarchy which will retain it until its superview leaves the view hierarchy.
To clarify best practice re IBOutlet references, as the Resource Programming Guide: Nib Files document says:
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. (The nib-loading code does not recycle nib file objects from a previous load attempt.) 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.
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 should therefore typically be weak, because:
Outlets that you create to subviews of a view controller’s view or a window controller’s window, for example, 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).
And note while this only has one parenthetical reference to storyboards, most of this discussion applies equally well to storyboards as to NIBs.
So, if your label is an IBOutlet that you've hooked up in Interface Builder, use weak.
If you perform an addSubview of a manually instantiated label, that addSubview will ensure that the view maintains a strong reference to the label for you (until such point that you remove it from its superview, or that view, itself, is deallocated), so you don't need to maintain any additional strong references to it, nor do you need to worry about it being released when the local variable falls out of scope.
In case 1, your object (presumably a view controller) has a strong reference to titleLabel. The declaration of the property does not tell us anything about the reference held to titleLabel by the label's superView (which is presumably self.view, not self). You could presume that self.view is a strong reference and you would assume that the view would retain a strong reference to its subviews - of which titleLabel is one - and that titleLabel would retain a weak reference to its super view.
In case 2 your object has a weak reference to titleLabel. This does not change the way in which your object holds a reference to its view nor how that view holds a reference to its sub views nor how titleLabel holds a reference to its super view.
In case 3 a weak reference will work because there are enough references being held through the view hierarchy to prevent titleLabel from being release prematurely.
In all cases the release of objects will be handled through the view controller lifetime methods that ensure that the view and its subviews are removed recursively when the view controller is removed

Creating IBOutlets as ivars on ARC. Memory issues?

I'm aware best practices for Objective-C development says IBOutlets should always be defined as properties according to Apple.
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.
But for learning purposes let's say we got the following scenario using ARC:
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController{
IBOutlet UIButton *buttonA;
IBOutlet UIButton *buttonB;
IBOutlet UIButton *buttonC;
}
#end
If I'm not mistaken, those three buttons are strong, so my question is: Will those buttons be released from memory once the ViewController is released?
Those buttons would be released automatically if they were weak, I know that, but not sure if they are strong.
Can anyone please help? Just to be clear, the method 'dealloc' on DetailViewController is empty.
You asked:
If I'm not mistaken, those three buttons are strong, so my question is: Will those buttons be released from memory once the ViewController is released?
Yes. Or, more accurately, those buttons will be deallocated when there are no more strong references. And in this scenario, those buttons now have two strong references, one being the view controller and another being the view to which these buttons were added as subviews. Both of those strong references would need to be relieved before the button would be deallocated.
But why would you want to maintain two strong references to that control? Generally you let the view maintain the strong reference to its subviews (i.e. let the view "own" its subviews), and the view controller is only using a weak reference to those subviews.
Those buttons would be released automatically if they were weak, I know that, but not sure if they are strong.
When the view controller has the weak reference, the buttons are being released because the only strong reference to the button is maintained by its superview and when that view is removed, then the button will lose its last strong reference and can be deallocated.
If the view controller has a strong reference, you are unnecessarily added another strong reference that needs to be relieved before the buttons are deallocated. You can do that, but it's unnecessary. You quoted from the Resource Programming Guide, but the preceding sentence says "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."
Bottom line, your example with the implicitly strong references to the IBOutlet controls will work fine. But there's no advantage to having the view controller maintain a strong reference to the buttons and it represents a bit of a misunderstanding of the object graph. View controllers really should only be maintaining weak references to the controls on their views.
Yes, when the ViewController is released, even its strongly referenced objects will be released. (Unless of course, some other non-released object holds a strong reference to them.)
There's a good discussion of weak and strong here: Explanation of strong and weak storage in iOS5

Is it possible that a weak reference might be garbage collected while I am using its parent in IOS?

Say I have a parent UIView. This UIView has a weak pointer to a subview UIImageView. If UIView is currently displayed on the screen, is it possible for the image view to be garbage collected since the parent UIview only has a weak reference to the UIImageView?
FYI UIview and UIImageView would both be on the screen
This UIView has a weak pointer to a subview UIImageView
Stop. If the UIImageView is a subview of the UIView, then the UIView has a strong pointer to the UIImageView. End of story.
In other words, a view retains its subviews. As long as the subview is a subview, it cannot vanish in a puff of smoke.
Now, on the other hand, if you remove that subview, then you have to worry about its memory management or it might vanish in a puff of smoke.
You use 'weak' property on subviews when they're expected to be created and directly added to a view subviews hierarchy : UIView addSubview: already keeps a strong reference to the view.
if your view is a weak property of a UIViewController, you typically create if from NIB, or in -(void)viewDidLoad. If the controller's view is discarded because not needed anymore, your subview will be too.
When you add a subview to your view, it will, by definition, maintain a strong reference to that subview. That's just part of the addSubview internal process of maintaining view hierarchies. The view will keep this strong reference to its subviews until that subview is manually removed (e.g., via removeFromSuperview) or if the superview, itself, is removed (e.g. you dismissed its view controller).
These strong references that views internally maintain on their subviews should not be confused with the weak references that you (or IB) might add to your view or view controller subclass .h file. Those weak references are just providing you a convenient way of referencing the subview or control. The fact that your .h file has a weak reference to the the subview, such as an IBOutlet for your benefit, doesn't alter the fact that views automatically already have a strong reference to their subviews behind the scenes as part of the overall view hierarchy.
So, a subview, such as an image view will only get deallocated when its last strong reference is removed (or in non-ARC language, when the retain count falls to zero). If you've added the image view as a subview, it won't get deallocated until that strong reference is eliminated (i.e. the image view is removed from it's superview, or the superview, itself is removed). Obviously, if you're maintaining other strong references to the control, those would have to be removed, as well, for the subview to be released.
A caveat: If you're not using ARC, i.e., you're doing manual reference counting (e.g. manually calling release and autorelease), it's certainly possible for you to make a programming mistake and "over release" the image view, thereby letting the retain count fall to zero, and thus allowing it to be deallocated prematurely. But given that you're referencing weak properties in your question, you must be using ARC, so this observation is moot.
There are other situations in which sloppy use of weak variables can cause problems, but I hesitate to elaborate unless you tell us that the subview is not showing up at all.
(By the way, you mention garbage collection (GC) in your question, but I assume the real question was "is it possible that my subview might be deallocated while ...". Obviously, iOS doesn't have GC. But I assume the real question is whether your subview might be deallocated while it's still present on its superview.)
If the UIVIew has the UIImageView added to it the reference will be incremented by that action wouldn't be released until it was removed from the view.
Without knowing why you asked this I would also say that I don't think there would be any harm in having a string reference to it because at the point where the UIView is cleaned up it would also dereference the the uiimageview and it would be released then.
Also I know you said garbage collected but iOS doesn't have garbage collection. I know what you mean though

Resources