Why there is no connection between UINavigationController and UIViewControllers

Situation: There is a UINavigationController with a pressed UIViewController.

1.UIViewController has a strong link to UINavigationController

@property(nonatomic,readonly,retain) UINavigationController *navigationController 

2.UINavigationController stores view controllers in NSArray

 @property(nonatomic,copy) NSArray *viewControllers; 

The UINavigationController must have a strong reference to this NSArray (or it will be freed).

3.NSArray has strong links to the built-in view controllers.

UPDATE: Suppose somewhere in the code we have the following:

 UIViewController *A = [ [UIViewController alloc] init ]; UINavigationController *B = [ [ UINavigationController alloc ] initWithRootViewController:A ]; // Here we have strong reference in A to B, in B to B.viewControllers (count == 1) and in B.viewControllers to A. // Local variable strong references to A and B A = nil; B = nil; // Local variable strong references has gone // But we should still have retain loop here // Magic !?? :) 

My question is, why don't we have a save loop here?

+7
ios objective-c cocoa-touch retain-cycle
source share
2 answers

2.UINavigationController stores view controllers in NSArray

This is not a given.

 @property(nonatomic,copy) NSArray *viewControllers; 

This in no way indicates that there is an ivar called _viewControllers or something like that. He just tells us that there is some method -viewControllers that -viewControllers will return to us, and that there is some setViewControllers: method that will accept it and hints that it will make a copy of it (or at least behave as if he made a copy). That is all that tells us. If you deploy the NSNavigationController in the debugger, you will notice that there are no _viewControllers ivar there.

If you orient yourself a bit, you will find that -viewControllers not implemented as a synthesized property. It just goes to -childViewControllers (which is a property of the UIViewController ). Well, is this not just a problem? I mean -childViewControllers implemented as [NSArray arrayWithArray:_childViewControllers] . Fair. You caught me.

But the same logic applies to [UIViewController navigationController] . This expression:

 @property(nonatomic,readonly,retain) UINavigationController *navigationController 

does not mean that he really has a strong connection. It just means that if you called setNavigationController: you expected it to save it. But you cannot call setNavigationController: There is no such method (not even private). So, all this is very promising, so that there is a method called -navigationController . And it is implemented as a call +[UINavigationController _ancestorViewControllerOfClass:allowModalParent:] . It just moves on to the implementation of the UIViewController , which moves along the chain of the parentViewController that searches for the UINavigationController . Thus, there is no save loop; it is dynamically determined.

But your question is still good. The header file here is misleading IMO, and I would open a radar against it. navigationController should be specified as assign or it should not say anything (even if this does not match strong by default, this is at least not misleading).

By the way, if this material interests you, you really should give up $ 90 for Hopper . This is very good with such a study.

+13
source share

The viewControllers UINavigationController property is defined as

 @property(nonatomic, copy) NSArray *viewControllers 

View controllers that are currently in the navigation stack.

Then there is no problem hold cycle, as the navigation controller removes any UIViewController from this array when the view manager deviates.

Loop delay is a problem when you don't have a mechanism to open a loop by releasing a held object at some point (using release , if not ARC, or set the strong property to nil ).

+2
source share

All Articles