无限导航堆栈

时间:2018-10-29 14:33:19

标签: ios swift

我最近接受了一次采访。

有人问我如何处理无限导航控制器,例如Wikipedia或IMDB。

如果我们将许多UIViewControllers堆叠到NavigationController上,则会收到内存警告或由于内存问题而崩溃。

我想知道如何解决此问题或采用什么方法?

4 个答案:

答案 0 :(得分:2)

UINavigationController在其堆栈中将视图控制器数组保留在内存中。它似乎不适合该任务。

在我看来,解决方案将是采用导航控制器样式的父视图控制器,但这需要其子视图控制器符合序列化/反序列化协议(Codable是一个不错的选择。)称之为InfiniteNavigationController。 InfiniteNavigationController会在将子视图控制器推入导航堆栈时对其进行序列化,并在需要将其显示在堆栈顶部时对其进行反序列化。

要真正达到无限,它可能应将其反序列化的子视图控制器的堆栈保存到磁盘上(并具有一种随机访问的方式来获取子数据,而无需将整个视图控制器的堆栈读取到内存中),尽管这可能不是必需的在实践中,因为序列化的视图控制器堆栈应具有非常低的内存需求。

答案 1 :(得分:1)

我要说的是,您应该创建一个观察者,该观察者在导航堆栈中查看viewControllers数组(显而易见),并且该条件从堆栈中删除一个(或多个),但是它会记住它们的位置和模型,这些位置和模型用于提供数据以绘制ViewController 。可以使用序列化将其写入磁盘以释放内存。

Apple也有interesting mechanism to restore viewcontrollers state,但我不确定您的问题是否可以接受。

答案 2 :(得分:1)

使用UINavigationController.setViewControllers(_:animated)

可以轻松实现

诀窍是,堆栈上始终只有一个控制器,而不是弹出控制器,而是先将其添加到堆栈并弹出:

let currentControllers = navigationController.viewControllers 
let previousController: UIViewController = ...
navigatonController.setViewControllers([previousController, currentControllers.last!], animated: false]
navigationController.popViewController(animated: true)

以及要推送的时间:

let nextController: UIViewController = ...
navigatonController.setViewControllers([nextController], animated: true)

还必须确保不要将控制器保留在内存中-必须一直重新创建,否则内存消耗不会改善。

另一个更复杂的解决方案是实现自己的容器组件,在顶部添加一个UINavigationBar。此解决方案的唯一问题是动画与UINavigationController动画会稍有不同。

答案 3 :(得分:0)

您需要管理

navigation.viewControllers = []