实现 UI 状态恢复时需要做的第一件事是从使用 didFinishLaunchingWithOptions 更改为 willFinishLaunchingWithOptions。如果您现在在 willFinish 中设置委托,则将按预期调用折叠。问题可能是代理设置得太晚,没有你的特殊处理就已经崩溃了。
另一个问题是,在横向和纵向时,控制器的恢复路径不同,因此可能会处于奇怪的状态。由于更改,它无法自动找到现有的详细视图控制器并创建新实例,并且由于详细信息项的配置错误,拆分视图委托可能会丢弃这两个或其中一个实例。在第 3 步的“重新创建您的视图控制器”下的 State Restoration 文档中,它说它会查找具有相同路径的已创建视图控制器,但在方向/特征更改后恢复时遗憾地失败,因为路径不同。因此它会退回到第 4 步并创建一个全新的空配置错误的详细控制器,这就是您看到控制器配置错误的原因。
要了解恢复标识符路径,请在应用委托中实现 application:viewControllerWithRestorationIdentifierPath:coder: 并输出路径组件,您将在纵向上看到最后要恢复的样子:
SplitViewController,
MasterNavigationController,
DetailNavigationController,
DetailViewController
...对应于拆分视图控制器的单一层次结构主要(注意:DetailNavigationController 在此配置中是隐藏的嵌套导航控制器)。
在景观中,最后两个要恢复的是:
SplitViewController,
MasterNavigationController,
MasterViewController
和
SplitViewController,
DetailNavigationController,
DetailViewController
...对应于拆分视图的主要和次要控制器层次结构。
所以现在知道 DetailViewController 的恢复路径可能不同,您可以理解,如果您尝试自动恢复纵向路径,而情节提要已在横向中初始化,它将找不到该详细视图控制器并求助于创建一个新的一。所以我认为解决方案是帮它找到它,不管恢复路径是如何保存的:
- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder{
if([identifierComponents.lastObject isEqualToString:@"DetailViewController"]){
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *secondaryNavigationController = splitViewController.viewControllers.lastObject;;
DetailViewController *detail = (DetailViewController *)secondaryNavigationController.viewControllers.firstObject;
return detail;
}
return nil;
}
现在恢复将正确使用已正确配置的现有细节控制器,并且不会被拆分视图委托丢弃,从而导致您只剩下主控。
这个问题的另一种表现方式是在恢复后看到两个细节控制器被推到导航堆栈上,如果你强制拆分视图委托不丢弃初始细节控制器,就会发生这种情况,当恢复创建另一个你最后推了两个!