为什么UINavigationController和UIViewControllers之间没有保留循环

Avt*_*Avt 8 cocoa-touch objective-c ios retain-cycle

情况:UINavigationController有UIViewController.

1.UIViewController强烈引用UINavigationController

@property(nonatomic,readonly,retain) UINavigationController *navigationController
Run Code Online (Sandbox Code Playgroud)

2.UINavigationController在NSArray中存储视图控制器

@property(nonatomic,copy) NSArray *viewControllers;
Run Code Online (Sandbox Code Playgroud)

UINavigationController应该具有对此NSArray的强引用(或者它将被释放).

3.NSArray强烈引用包含的视图控制器.

更新:让我们想象代码中的某个地方,我们有以下内容:

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's strong references to A and B
A = nil; B = nil;
// Local variable's strong references has gone
// But we should still have retain loop here
// Magic !?? :)
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么我们这里没有保留循环?

Rob*_*ier 15

2.UINavigationController将视图控制器存储在 NSArray

那不是一个给定的.

@property(nonatomic,copy) NSArray *viewControllers;
Run Code Online (Sandbox Code Playgroud)

这绝不表示有一个叫做的ivar _viewControllers或类似的东西.它只是告诉我们,有一些方法-viewControllers将返回美国的NSArray,并且有一些方法setViewControllers:,将接受一个,并暗示它会使它的一个副本(或至少表现得像它做它的一个副本).这就是它告诉我们的一切.如果NSNavigationController在调试器中展开a ,您会注意到那里没有_viewControllers列出的ivar.

如果你捅了一下,你会发现它-viewControllers并没有作为综合属性实现.它只是前进-childViewControllers(这是一个UIViewController属性).好的,那不就是移动问题吗?我的意思-childViewControllers 实现为[NSArray arrayWithArray:_childViewControllers].很公平.你抓住了我

但同样的逻辑适用于[UIViewController navigationController].本声明:

@property(nonatomic,readonly,retain) UINavigationController *navigationController
Run Code Online (Sandbox Code Playgroud)

并不意味着它实际上有很强的联系.它只是意味着如果你打电话setNavigationController:,你会期望它保留它.但你不能打电话setNavigationController:.没有这样的方法(甚至不是私人方法).所有这一切都很有希望的是有一个叫做的方法-navigationController.而它的实现为一个呼叫+[UINavigationController _ancestorViewControllerOfClass:allowModalParent:].这只是传递给UIViewController实现,它parentViewController正在寻找一个链UINavigationController.所以没有保留循环; 它是动态决定的.

但你的问题仍然很好.这里的头文件令IMO感到困惑,我会打开它的雷达.navigationController应该被列为assign或者它应该什么都不说(即使违约strong它至少不会产生误导).

顺便说一句,如果这些东西让你感兴趣,你真的应该为Hopper降价90美元.这种探索非常好.