Domanda

Setup

I have a sliding menu custom container view controller (MMDrawerController) controlling a center view controller and a slide out left menu/drawer. Just like the Facebook app and hundreds of others.

Opening the drawer on the left and tapping a menu item replaces the center view controller.

What's Working

If I open the app, press a button on the first center view controller (which changes the background color), I can kill the app and successfully restore the background color. Perfect.

What's Not Working

If I choose another center vc to load (by opening up the menu/drawer and selecting a menu option) and then kill the app, the app won't restore to that view controller.

What I'm Doing

In my parent view controller I'm encoding the left and center view controllers so I can recreate them on restore.

- (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];
}

In the flow where I change the color on the first center view controller, during decoding I can get back the center and left View Controllers successfully. However in the flow where I select a new center vc to load, during decoding those objects are nil.

How do I set up my custom container view controller to properly encode references to it's children in a way that I'm guaranteed to get them back while decoding?

UPDATE 1

Using the restorationArchiveTool I inspected the archive after running through the scenario that doesn't restore properly, and the archive does in fact contain the hierarchy of encoded objects that I'd expect. I still can't figure out though why those previously encoded view controllers end up being null during decoding.

UPDATE 2 If you look at the comments section of this gist, you can see that all the proper encode/decode calls seem to be happening on saving and restoring. I'm wondering if in my app delegate, when i initially set up my root view controller (the instance of mmdrawercontroller) if I'm somehow clobbering the state restoration? Here's what I'm doing:

- (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;
}
È stato utile?

Soluzione

I have done similar with MMDrawerController and believe the problem is that you are not providing UIKit with a way to create all of the possible center view controllers when it is restoring state. Note that when you encode a controller, all that gets saved is the restoration ID for that controller. To be restored when you next start the app UIKit needs to be able to obtain an instance of the controller -- it won't create one itself. It will try various methods to obtain said instance, as listed here:

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

Your app may create the default center controller every time (either via a storyboard or manually) so that one works. For others you probably need to either implement a restoration class or implement application:viewControllerWithRestorationIdentifierPath:coder: in your delegate and have it return a new instance of the right type.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top