Why doesn't my app return to my detail view when it's restored?

痞子三分冷 提交于 2019-12-19 10:11:53

问题


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.


回答1:


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.




回答2:


In the iOS App Programming Guide, section "State Preservation and Restoration" there is a convenient checklist for what you have to do to make restoration work.

After looking at your code it seems that you forgot step 3, Assign Restoration Classes. Your classes do not have these properties, and you did not implement viewControllerWithRestorationIdentifierPath in the app delegate.

Assign restoration classes to the appropriate view controllers. (If you do not do this, your app delegate is asked to provide the corresponding view controller at restore time.) See “Restoring Your View Controllers at Launch Time.”




回答3:


I took a look at your sample and the applicationWillFinishLaunching is missing [self.window makeKeyAndVisible] which is a requirement for state restoration. This will make the split controller immediately collapse and then it will be restored correctly.

There is an issue that if it was preserved in landscape, i.e. separated split view , and then launched in portrait then the path will not be correct. In this case at launch it will first collapse to match the current screen, then it begin restore and first separate, then after restore has finished it will collapse again to match the current screen. During this time you need to implement viewControllerWithRestorationIdentifierPath and use the last string in the path to identify the controller and return it after having captured it from what the storyboard created initially in will finish launching. Then you can clear those properties in didFinish.



来源:https://stackoverflow.com/questions/19218235/why-doesnt-my-app-return-to-my-detail-view-when-its-restored

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!