Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIViewController lifecycle calls in combination with state restoration

I'm trying to implement state restoration in an app that uses iOS 6+ and storyboards, but I am having problems finding a way to prevent duplicate calls to heavy methods.

If I simply start the app, then I need to setup the UI in viewDidLoad:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupUI];
}

This works fine in a normal, non-state-restoration world. Now I've added state restoration and after restoring some properties I need to update the UI with those properties:

- (void)decodeRestorableStateWithCoder:(NSCoder *)coder {
    [super decodeRestorableStateWithCoder:coder];
    // restore properties and stuff
    // [...]
    [self setupUI];
}

So what happens now is that first the setupUI method is called from viewDidLoad, and then again from decodeRestorableStateWithCoder:. I don't see a method that I can override that's always called last.

This is the normal order of method calls:

  • awakeFromNib
  • viewDidLoad
  • viewWillAppear
  • viewDidAppear

When using state restoration, this is called:

  • awakeFromNib
  • viewDidLoad
  • decodeRestorableStateWithCoder
  • viewWillAppear
  • viewDidAppear

I can't place the call to setupUI in viewWillAppear because then it would also be executed every time you native back to a view.

It would be much handier if decodeRestorableStateWithCoder was called BEFORE viewDidLoad because then you could use restored properties. Sadly that not the case, so... how can I prevent doing the work in viewDidLoad when I know that I need to do it all over again in decodeRestorableStateWithCoder right after?

like image 309
Kevin Renskers Avatar asked Aug 07 '13 15:08

Kevin Renskers


People also ask

What is state restoration?

State restoration is an often-overlooked feature in iOS that lets a user return to their app in the exact state in which they left it – regardless of what's happened behind the scenes. At some point, the operating system may need to remove your app from memory; this could significantly interrupt your user's workflow.

What is the role of UIViewController?

The UIViewController class defines the shared behavior that's common to all view controllers. You rarely create instances of the UIViewController class directly. Instead, you subclass UIViewController and add the methods and properties needed to manage the view controller's view hierarchy.

What is a view controller in swift?

A view controller manages a single root view, which may itself contain any number of subviews. User interactions with that view hierarchy are handled by your view controller, which coordinates with other objects of your app as needed. Every app has at least one view controller whose content fills the main window.


1 Answers

If you're doing state restoration programatically (i.e. not using storyboards), you can use + viewControllerWithRestorationIdentifierPath:coder:, init the view controller there and use whatever you need from the coder to do your pre-viewDidLoad initialization.

+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
    if ([[identifierComponents lastObject] isEqualToString:kViewControllerRestorationIdentifier]) {
        if ([coder containsValueForKey:kIDToRestore]) {
            // Can only restore if we have an ID, otherwise return nil.
            int savedId = [coder decodeIntegerForKey:kIDToRestore];
            ViewController *vc = [[ViewController alloc] init];
            [vc setThingId:savedId];
            return vc;
        }
    }

    return nil;
}

I've found that trying to implement state restoration has shown up bad programming practices in my code, like packing too much into viewDidLoad. So while this works (if you're not using storyboards), the other option is to refactor how you're setting up your view controllers. Instead of using a flag, move code pieces to their own methods and call those methods from both places.

like image 177
nevan king Avatar answered Sep 19 '22 13:09

nevan king