标签栏和导航控制器应用程序中的状态恢复

Posted

技术标签:

【中文标题】标签栏和导航控制器应用程序中的状态恢复【英文标题】:State Restoration in Tab Bar and Navigation Controller App 【发布时间】:2015-09-09 05:26:31 【问题描述】:

目标:我正在尝试恢复基于标签控制器的应用的状态(每个标签上都有导航控制器)。

问题:重新启动时,选定的选项卡似乎已按预期恢复,但所述选项卡内的导航层次结构却没有。

发展:

    我首先从项目模板“基于选项卡的应用程序”开始。 接下来,我将恢复 ID 添加到子视图控制器和标签栏控制器。 在应用委托中,我实现了application(_:shouldSaveApplicationState:)application(_:shouldRestoreApplicationState:)

然后我运行应用程序,切换到第二个(右侧)选项卡,点击主页,终止。 o 重新启动,显示右侧选项卡(如预期的那样)。 到目前为止一切顺利。

    接下来,我转到情节提要,将两个子视图控制器嵌入到各自的导航控制器中,并为它们分配恢复 ID。

我运行该应用程序,恢复仍然有效。 还是不错的。

    接下来,我添加一个“细节”视图控制器;它的类是故事板的 UIViewController 的自定义子类,具有配置调试标签内容及其视图背景颜色的属性。

    我在每个选项卡的顶部视图控制器上放置了一个“显示详细信息...”按钮,并从每个选项卡创建一个转场到(共享)详细视图控制器。所以现在我的故事板看起来像一个六边形(另外,两个 segue 都在 Interface Builder 中设置了标识符)。因此,左右顶视图控制器共享相同类型的“细节”视图控制器。在展示时,它被配置为与被推送的位置区分开来(见下一点)。

    在每个顶视图控制器的prepareForSegue(_:sender:) 方法中,我对推送的详细视图控制器进行了不同的配置:不同的文本和背景颜色(分别为“左”和蓝色,“右”和红色)。

    我在细节视图控制器中添加了代码来保存和恢复文本和背景颜色属性的状态:encodeRestorableStateWithCoder(_:)decodeRestorableStateWithCoder(_:)。另外,我实现了viewDidLoad(),以便在视图中反映这些属性的值。每当它被实例化并通过 segue 推入导航时,首先设置属性,然后用于在viewDidLoad() 中配置视图。每当它在恢复期间被实例化时,属性都会在decodeRestorableStateWithCoder(_:) 中设置,并在viewDidLoad() 中类似地使用。

...但是当我运行此代码时,最后选择的选项卡会恢复,但只能到顶视图控制器-左或右-,不是细节 .有趣的是,最后为细节视图控制器设置的背景颜色会瞬间闪烁。

我在encodeRestorableStateWithCoder(_:)decodeRestorableStateWithCoder(_:) 中放置了断点,但只执行了第一个(encode)。

    想知道可能缺少什么,我继续实现了应用程序委托的 application(_:viewControllerWithRestorationIdentifierPath:coder:)(始终返回 nil,但记录路径组件已通过)。

文档对于是否需要此方法不是很清楚,并且在任何情况下,除了细节之外的所有视图控制器似乎都可以完美恢复,即使没有它。我添加了代码以根据最后一个路径组件(即该控制器的恢复 ID)实例化每个视图控制器并返回它。

现在,decodeRestorableStateWithCoder(_:) 被调用了,但导航在片刻之后仍会返回到选项卡的顶部视图控制器。

那么,到底发生了什么?在标签栏 + 导航控制器应用程序中实现状态保存和恢复我缺少什么?

【问题讨论】:

【参考方案1】:

已修复:所以,我的代码有几个问题...

    事实证明,就我而言,我不需要实现application(_:viewControllerWithRestorationIdentifierPath:coder:)。 (见comments of this answer)

    encodeRestorableStateWithCoder(_:)decodeRestorableStateWithCoder(_:) 的实现 没有打电话给super(如accepted answer对上述问题的建议)。

    最后,我得到了正确的视图控制器(细节),但它的子视图的状态(文本标签内容和主视图背景颜色)处于初始的空状态(没有恢复到最后的状态-即,文本标签内容和背景颜色)。正如this question 中提到的,viewDidLoad() notdecodeRestorableStateWithCoder(_:) 之后被调用(就像我假设的那样),所以我从viewDidLoad()decodeRestorableStateWithCoder(_:) 调用一个通用方法来更新用户界面。

像往常一样,我在搜索或尝试对我的代码进行足够的修改之前急于发布一个问题(我很抱歉......)。

我希望这至少对其他人有所帮助。

像往常一样,我会等几天再接受我自己的答案,以防有人进一步阐明。

【讨论】:

以上是关于标签栏和导航控制器应用程序中的状态恢复的主要内容,如果未能解决你的问题,请参考以下文章

iOS MapView 位于导航栏、状态栏和标签栏控制器下

如何在视图控制器中的标签栏和导航栏上全屏显示弹出视图?

Xcode 13 - swift OS 15 中的导航栏和状态栏文本颜色变化

iOS 11、状态栏、导航栏和 UIScrollview

标签栏和导航控制器在视图控制器中看不到了

组合标签栏和导航栏控制器出现问题