简体   繁体   中英

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.

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.

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".

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM