Set the Storyboard ID for the navigation controller and the table view controller and select the “Use Storyboard ID” option to use the same identifier for the restortation ID. Also set the restoration ID for the table view.

Build and run

Scroll down the table view until row 50 is the first visible row. Use the home button to move the App to the background and then use Xcode to stop the App.

Run the app again to see the restored state.

Expected Results

The first visible row should be row 50 which was the first visible row when the App was terminated.

Actual Results

The first visible row is row 0.

Regression

Delete the navigation controller from the storyboard and repeat the test. On restoring the app the first visible row is row 50.

Notes

A sample Xcode project to reproduce the problem can be found in my GitHub Code Examples repository. The project contains two storyboards to demonstrate state restoration of a table
view both when it is the root view and when it is embedded in a navigation
controller:

If the Target settings are used to set the Main Storyboad to NavStoryboard the
user interface consists of UITableView embedded in a Navigation Controller. In
this use case the table view state is not restored.

If the Target settings are used to set the Main Storyboard to MainStoryboard the user interface consists of a single UITableView which does have state restored as expected.

Workarounds

Apple engineers suggested the following workaround which I can confirm resolves the issue:

Please do the following in the ViewController that owns the TableView: