我最近接受了一次采访。
有人问我如何处理无限导航控制器,例如Wikipedia或IMDB。
如果我们将许多UIViewControllers
堆叠到NavigationController
上,则会收到内存警告或由于内存问题而崩溃。
我想知道如何解决此问题或采用什么方法?
答案 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 = []