My app has a simple organization, which I've configured in an Interface Builder storyboard (not in code). There is a Navigation View Controller, which has its Root View Controller set to my Main View Controller. My Main View contains a table, where cells segue to a Detail View Controller.
When I suspend the application while looking at the Detail View and then resume it, I'm returned to the Main View, rather than the Detail view. Why might this be?
Details:
I have set Restoration IDs in Interface Builder for the Navigation View Controller, the Main View Controller and the Detail View Controller. I've also tried adding a Restoration ID to the Table View and making the Main View Controller implement UIDataSourceModelAssociation.
My app is returning YES from shouldRestoreApplicationState and both the Main View and the Detail View have encode/decodeRestorableStateWithCoder methods.
I'm testing suspend/resume using the simulator: I run the app, navigate to the Detail View, hit the home button, and then click the stop button in XCode. To resume, I'm running the app again from XCode.
I see the following calls on suspend:
AppDelegate shouldSaveApplicationState
MainViewController encodeRestorableStateWithCoder
DetailViewController encodeRestorableStateWithCoder
And on resume:
AppDelegate shouldRestoreApplicationState
AppDelegate viewControllerWithRestorationIdentifierPath Navigation
AppDelegate viewControllerWithRestorationIdentifierPath Navigation/MainView
MainViewController viewDidLoad
AppDelegate viewControllerWithRestorationIdentifierPath Navigation/DetailView
MainViewController decodeRestorableStateWithCoder
In addition to the wrong view being restored, there's something else odd: Why is the Restoration Identifier Path for the Detail View "Navigation/DetailView" and not "Navigation/MainView/DetailView"? There is no direct relationship between the Navigation View Controller and the Detail View Controller. Their only connection in Interface Builder is via the segue from the Main View.
Have I misconfigured something?
I have tried assigning a Restoration Class to the Detail View. When that restoration code is invoked, it fails because the UIStateRestorationViewControllerStoryboardKey is not set in the coder.
Here's a toy version of my project which replicates the problem: https://github.com/WanderingStar/RestorationTest
I'm trying this with XCode Version 5.0 (5A1413) and iOS Simulator Version 7.0 (463.9.4), in case those are relevant.
The answer turned out to be simple: I was not calling
[super encodeRestorableStateWithCoder:coder];
in the encodeRestorableStateWithCoder:coder
method in my View Controllers (and doing the same in decode...) which is what sets the storyboard in the coder.
This tutorial helped me step through each step of the process, and find out where I'd gone wrong: http://useyourloaf.com/blog/2013/05/21/state-preservation-and-restoration.html
Also, it turns out that "Navigation/DetailView" is what's expected. The Navigation View Controller restores all of the views in its stack and then puts them back into the stack, rather than each view restoring the later views in the stack.