9

情况:有推送 UIViewController 的 UINavigationController。

1.UIViewController强引用UINavigationController

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

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

@property(nonatomic,copy) NSArray *viewControllers;

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 !?? :)

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

4

2 回答 2

15

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

这不是给定的。

@property(nonatomic,copy) NSArray *viewControllers;

这绝不表示有一个 ivar 被调用_viewControllers或类似的东西。它只是告诉我们有一些方法-viewControllers会返回一个NSArray,并且有一些方法setViewControllers:会接受一个,并暗示它将复制它(或至少表现得像复制了它)。这就是它告诉我们的全部。如果您NSNavigationController在调试器中展开 an,您会注意到那里没有_viewControllers列出 ivar。

如果您稍微浏览一下,您会发现它-viewControllers没有作为综合属性实现。它只是转发到-childViewControllers(这是一个UIViewController属性)。好的,那不只是解决问题吗?我的意思-childViewControllers 实现为[NSArray arrayWithArray:_childViewControllers]. 很公平。你抓住了我。

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

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

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

但你的问题仍然是一个好问题。这里的头文件使 IMO 感到困惑,我会针对它打开一个雷达。navigationController应该被列为assign或者它应该什么都不说(即使默认strong它至少不会误导)。

顺便说一句,如果你对这些东西感兴趣,你真的应该花 90 美元买Hopper。它非常擅长这种探索。

于 2014-02-23T01:44:26.723 回答
2

viewControllers属性UINavigationController定义为

@property(nonatomic, copy) NSArray *viewControllers

当前在导航堆栈上的视图控制器。

然后没有问题的保留循环,因为UIViewController当视图控制器被解除时,导航控制器会从该数组中删除任何内容。

当您没有任何机制通过在某个点释放保留的对象(使用releaseif non-ARC 或将 strong 属性设置为nil)来打开循环时,保留循环是一个问题。

于 2014-02-22T20:53:08.273 回答