2
votes

I'd like to implement state preservation and restoration in my iOS 6 app that doesn't use storyboards. My main view controller that I want to save state and restore is a UIViewController that's part of the UINavigationController.

My view controller extends UIViewControllerRestoration protocol. I think I'm implementing all of the necessary methods yet I don't see any calls to the encodeRestorableStateWithCoder or decodeRestorableStateWithCoder from the simulator.

Here's what my app delegate looks like: MyAppDelegate:

- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder {
    NSLog(@"shouldSaveApplicationState"); // seeing this in the debug window
    return YES;
}

- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder {
    NSLog(@"shouldRestoreApplicationState"); // seeing this in the debug window
    return YES;
}

- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder {
    NSLog(@"willEncodeRestorableStateWithCoder"); // seeing this in the debug window
}

- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder {
    NSLog(@"didDecodeRestorableStateWithCoder"); // seeing this in the debug window
}

I see all of these calls in the debug window. Here's what my MyMainViewController, which is visible on app suspend, looks like:

@interface MyMainViewController : UIViewController <UIViewControllerRestoration>
@end

@implementation MyMainViewController

- (id)init {
    if (self = [super init]) {
        self.restorationIdentifier = @"MyViewControllerRestoreId";
        self.restorationClass = [self class];
    }
    return self;
}

- (void)loadView {
    self.view = [[UIView alloc] initWithFrame:frame];

    // Bunch of work to create my custom views
}

- (void)awakeFromNib {
    self.restorationClass = [self class];
}

// Expected a call to this method, but not seeing it in debug window
+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents
                                                            coder:(NSCoder *)coder {
    NSLog(@"viewControllerWithRestorationIdentifierPath: %@", identifierComponents);

    MyMainViewController *vc = [[MyMainViewController alloc] init];
    vc.restorationIdentifier = [identifierComponents lastObject];
    vc.restorationClass = [MyMainViewController class];

    return vc;
}

// Expected a call to this method, but not seeing it in debug window    
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
    NSLog(@"encodeRestorableStateWithCoder");
    [super encodeRestorableStateWithCoder:coder];
}

// Expected a call to this method, but not seeing it in debug window    
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder {
    NSLog(@"decodeRestorableStateWithCoder");
    [super decodeRestorableStateWithCoder:coder];
}    
@end

The way I use the simulator to test preservation and restoration:

1. Launch app in Simulator via Xcode
2. Invoke the Home key so App is now suspended. This where I see:
    shouldSaveApplicationState  
    willEncodeRestorableStateWithCoder
3. End the debugging session in XCode (Command .)
4. Start a new debug session of the app in XCode. I see:
    shouldRestoreApplicationState
    didDecodeRestorableStateWithCoder

I'm not sure what else I'm missing to make this work.

3
Have you got working this ? i'm stuck here :(I_User
@Jonas Gardner: Did you find what the issue is? I am having this issue too. Thanks!Loc

3 Answers

3
votes

I was having the exact same issue. Turned out, I needed to explicitly set the protocol on the view controller in order for the restorationClass to be used:

<UIViewControllerRestoration>

It seems like you have the done already, but that ended up doing it for me.

2
votes

This code might not be running:

- (id)init {
    if (self = [super init]) {
        self.restorationIdentifier = @"MyViewControllerRestoreId";
        self.restorationClass = [self class];
    }
    return self;
}

The designated initializer for a view controller is initWithNibName:bundle:, so there's no guarantee that its init is ever called. Plus, if the view controller is coming from a xib or storyboard, neither of those methods is ever called.

You do have an awakeFromNib implementation:

- (void)awakeFromNib {
    self.restorationClass = [self class];
}

That will run if the view controller is coming from a xib or a storyboard, but then in that case you've forgotten to assign the restorationID.

1
votes

Don't know if this will help or make a difference as I'm just learning state preservation/restoration myself, but here are something you may try I got from the tutorial I'm working out of.

If your VC is in a TabBar or NavController make sure they have a restorationIdentifier also.