使用自定义容器视图控制器(MMDrawerController)进行iOS状态恢复

时间:2013-07-29 21:37:29

标签: iphone ios objective-c uiviewcontroller state-restoration

设置

我有一个滑动菜单自定义容器视图控制器(MMDrawerController)控制中央视图控制器和滑出左侧菜单/抽屉。就像Facebook应用程序和数百个其他人一样。

打开左侧的抽屉并点击菜单项会替换中央视图控制器。

什么在起作用

如果我打开应用程序,按第一个中央视图控制器上的按钮(更改背景颜色),我可以杀死应用程序并成功恢复背景颜色。完善。

什么不起作用

如果我选择另一个中心vc加载(通过打开菜单/抽屉并选择一个菜单选项)然后终止应用程序,该应用程序将无法恢复到该视图控制器。

我在做什么

在我的父视图控制器中,我正在编码左视图和中心视图控制器,以便我可以在恢复时重新创建它们。

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    [coder encodeObject:self.centerViewController forKey:@"centerVC"];
    [coder encodeObject:self.leftDrawerViewController forKey:@"leftDrawerVC"];
    [super encodeRestorableStateWithCoder:coder];
}

- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
    // if I don't change the center view controller, these values
    // get logged out as expected
    NSLog(@"leftDrawer: %@", [coder decodeObjectForKey:@"leftDrawerVC"]);
    NSLog(@"center: %@", [coder decodeObjectForKey:@"centerVC"]);
    [super decodeRestorableStateWithCoder:coder];
}

在我改变第一个中心视图控制器颜色的流程中,在解码过程中,我可以成功返回中心和左视图控制器。然而,在我选择要加载的新中心vc的流程中,在解码期间这些对象是零。

如何设置我的自定义容器视图控制器以正确编码对其子项的引用,以保证在解码时将它们取回?

更新1

使用restorationArchiveTool我在运行未正确恢复的方案后检查了存档,并且存档实际上包含了我期望的编码对象的层次结构。我仍然无法弄清楚为什么那些先前编码的视图控制器在解码期间最终为空。

更新2 如果您查看this gist的评论部分,您会发现所有正确的编码/解码调用似乎都在保存和恢复时发生。我想知道是否在我的应用程序委托中,当我最初设置我的根视图控制器(mmdrawercontroller的实例)时,如果我以某种方式破坏状态恢复?这就是我正在做的事情:

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UINavController *centerNav = [[UINavController alloc] initWithRootViewController:[FeaturedViewController new]];
    centerNav.restorationIdentifier = @"centerNav";
    UINavigationController *leftDrawerNavController = [[UINavigationController alloc] initWithRootViewController:[LeftDrawerViewController new]];
    leftDrawerNavController.restorationIdentifier = @"leftDrawerNav";

    MMDrawerController *drawerViewController = [[MMDrawerController alloc] initWithCenterViewController:centerNav leftDrawerViewController:leftDrawerNavController];

    // no restoration class, since this will always be created before state restoration resumes, and therefore will be found implicitly
    [drawerViewController setRestorationIdentifier:@"mmDrawer"];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.rootViewController = drawerViewController;
    self.window.restorationIdentifier = NSStringFromClass([UIWindow class]);
    self.window.backgroundColor = [UIColor whiteColor];

    [self.window makeKeyAndVisible];
    return true;
}

1 个答案:

答案 0 :(得分:1)

我与MMDrawerController做了类似的事情,并且相信问题是你没有为UIKit提供一种在恢复状态时创建所有可能的中心视图控制器的方法。请注意,对控制器进行编码时,保存的所有内容都是该控制器的恢复ID。要在下次启动应用程序时进行恢复,UIKit需要能够获得控制器的实例 - 它不会自己创建一个实例。它将尝试各种方法来获取所述实例,如下所示:

http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/StatePreservation/StatePreservation.html#//apple_ref/doc/uid/TP40007072-CH11-SW10

您的应用每次都可以创建默认的中央控制器(通过故事板或手动),以便一个可以工作。对于其他人,您可能需要在委托中实现恢复类或实现application:viewControllerWithRestorationIdentifierPath:coder:并让它返回正确类型的新实例。