2

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.

Jonas Gardner
  • 2,458
  • 5
  • 22
  • 28

3 Answers3

3

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.

AJ Venturella
  • 4,742
  • 4
  • 33
  • 62
  • Can you post some sample code of UIViewControllerRestoration? I tried as you said but it did not work. I am not using Storyboard. Thanks! – LHA Oct 21 '15 at 20:30
2

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
1

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.

vichudson1
  • 881
  • 1
  • 10
  • 21
  • Which tutorial are you using? – Jonas Gardner Aug 09 '13 at 19:36
  • That would be the ebook iOS 6 By Tutorials, found here http://www.raywenderlich.com/store/ios-6-by-tutorials – vichudson1 Aug 10 '13 at 01:08
  • That site has lots of great tutorials for free, but that particular is in the book. I own the iOS 5 & 6 books both. and plan to buy the iOS 7 book when available. Well worth the money in my opinion. – vichudson1 Aug 10 '13 at 01:10
  • Just to confirm, the tutorial isn't using storyboards for state preservation and restoration? – Jonas Gardner Aug 11 '13 at 05:26
  • No the tutorial uses storyboards specifically. In fact the only problems Ive had with state restoration not working was with a VC presented modally from a nib not in the story board. Put the VC in storyboard works fine, put it in external xib without any other changes and no joy. – vichudson1 Aug 11 '13 at 10:26