iPhone - UINavigationController,重用视图?

3
根本问题是“在不引起内存警告或触发看门狗终止的情况下,您可以将多少个UIViewControllers推送到导航堆栈上?”
假设我有一个应用程序,基本上是三个实体的数据库,每个实体都可以与其他实体建立关系,并在UIViewController上显示关系。用户可以跟随这些关系,每个关系都会带来一个新的控制器——如果实体是A、B和C,而A->B->C->B->C->A,则每种视图在堆栈上出现两次。我知道如何推送和弹出,如何返回到特定控制器,我认为最好重用导航堆栈中的视图控制器,而不是无限地扩展导航堆栈。
为了做到这一点,每当我想要一个FirstEntityViewController时,我可以扫描导航堆栈,找到一个对象,其中[self isKindOfClass:[FirstEntityViewController class]];然后调用设计用于重新调整该视图以显示我当前想要看到的内容的方法——只是刷新数据的方式,就像重用UITableViewCell时一样。
这很好,除了它可能对NavigationController产生的影响。如果我使用UINavigationController:popToViewController:animated:,我认为它将丢弃所有在我弹出的视图之上的东西,包括用户期望在导航栏中点击“返回”时找到的视图。因此,用户点击关系,然后点击返回,会感到困惑。
如果我从导航堆栈中删除匹配的控制器,然后将其弹出到堆栈顶部,那么返回行为仍然正常,只要用户没有回到被移动的FirstEntityViewController实例,否则导航将看起来不一致。
正确的解决方案是从堆栈中删除控制器,并以某种方式保留堆栈中的位置,以便当重用的控制器被弹出时,可以将其替换回原来的位置吗?我应该维护自己的视图类型和数据显示列表,以便在弹出时可以替换即将弹出的视图下面的视图,始终领先于返回导航?
还是说这太复杂了?是否根本不需要担心这种情况,因为操作系统以与UITableViewCells相同的方式重用大部分视图控制器,在具有50个深度的导航堆栈上没有真正的内存或性能影响?

听起来有两个问题:1)堆栈上可以有多少个元素,2)给定的元素是否可以在堆栈上出现多次?对吗? - Sixten Otto
有点这个意思。堆栈上可以有多少东西,肯定是可以的。某个特定的事物是否可以在堆栈上出现超过一次,我相当确定答案是肯定的,我只是担心允许它的影响(即didReceiveMemoryWarning)。解决方案可能是等待那个内存警告,然后开始寻找要删除的堆栈条目,例如最后一个“重要”视图之前的所有内容。 - Adam Eberbach
2个回答

4

ViewController实例一直保留在UINavigationController的堆栈中,但除了顶部视图之外的任何视图都可以随时卸载(通过viewDidUnload消息通知视图控制器)。

换句话说,在顶部视图下面的视图不会一直存在,并且最终会在低内存情况下被卸载,因此您无需尝试重用您的视图控制器。


当视图被卸载时,导航会发生什么情况 - 是否可以在缺失的视图之后链接并仍然允许返回,还是返回不再是一个选项? - Adam Eberbach
1
不。当视图再次出现时,它会通过loadView和viewDidLoad消息重新加载。您可以通过模拟低内存条件在模拟器中测试此功能。 - Darren

0

据我最近的检查,您无法将已经在导航控制器堆栈上的视图控制器再次推回到它上面。您需要创建一个新的视图控制器并将其推入堆栈中,每个返回按钮都会将其从堆栈中弹出。您能做的最好的事情就是制作一个视图控制器缓存,并根据需要分配它们 - 只要它们从导航控制器堆栈中弹出即可。但这可能不会为您带来太多的内存节省。

UITableViews 有点不同,因为在任何给定时间只有相对较少的单元格处于视图中,而且一旦单元格离开屏幕,它就会被移除并返回到池中。如果您可以保证链的最大深度是固定的,那么您可以采用类似的窗口方案。如果不能,您可能需要继续深入,并及时释放内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接