iPhone Dev: Saving State

I see every now and again that Apple needs to make it easier to allow developers to save the state of their application so that they open up exactly as they were when they were shut down.

Obviously I’m all for Apple making my life easy, but that’s not going to happen for a while yet so I thought I’d share how I implemented it in Yummy.

The key is this simple protocol:


@protocol SaveState

- (NSData*) saveState;
- (id) initWithSaveState:(NSData*)data;

@end

This is what I have in my applicationWillTerminate: method:


NSMutableArray* vcList = [NSMutableArray arrayWithCapacity:3];
for (UIViewController* vc in self.navigationController.viewControllers) {
    // Classes that don't implement the SaveState protocol will be ignored
    if ([vc conformsToProtocol:@protocol(SaveState)]) {
        NSArray* state = [NSArray arrayWithObjects:NSStringFromClass([vc class]),
                                                                     [(UIViewController*)vc saveState],
                                                                     nil];
        [vcList addObject:state];
    }
}

This is in the applicationDidFinishLaunching::


for (NSArray* screen in screenList) {
    UIViewController* next =
                [[NSClassFromString([screen objectAtIndex:0]) alloc]
                                   initWithSaveState:([screen count] == 2) ?
                                   [screen objectAtIndex:1] : nil];
    if (next != nil) {
        [[self navigationController] pushViewController:next animated:NO];
        [next release];
    }
}

So a simple example, for a view controller that needed to be remembered but didn’t need to store any extra state, would be:


- (NSData*) saveState {
    return nil;
}

- (id) initWithSaveState:(NSData*)data {
    return [self init];
}

But you can initialise each view controller with anything that can be converted into an NSData. (I picked NSData rather than, say, id because an NSData can always be serialised. Made sense to make that assumption.)

One weakness is that it doesn’t cope with the situation where a modal view is on top but that should be pretty easy to implement if it’s important (it generally isn’t in Yummy).


Comments

4 responses to “iPhone Dev: Saving State”

  1. Simon King avatar

    Hi

    I found the above very useful, the only thing that seems to be missing is where you’re storing the screenList when the app terminates or where it comes from when the app is launched again.

    Are you using NSUserDefaults to serialise and save state or are you using a custom mechanism?

    Other than that thanks for a very useful blog entry.

    Regards
    Simon

    1. Yes, I use NSUserDefaults. Though the answer really is “whatever is easiest.” I know some people store lots and lots of data in UIViewControllers (not good practice I’d argue). In this case I’d recommend something other than NSUserDefaults.

      1. Simon King avatar

        Thanks for the reply, although I store lots of data in my view controllers it’s always persisted to a sqlite db and saved immediately after every change so I should be fine.

        I’m going to ignore any modal controllers and just persist the pushed view controllers on the stack.

        This is the last thing to do for my first app so hopefully I can get that done out of the way now. Although for future apps I’ll build it in straight away.

        Cheers
        Simon

        PS is the reference to the ZX 81 Sinclairs first home computer? I had the Acorn Atom then moved to the ZX Spectrum.

        1. Yes, the ZX81 refers to the Sinclair computer. Here’s a longer answer: https://www.zx81.org.uk/about