IOS Saving State For Complex Apps
I'm building a fairly complex business application on the iPad IOS 4.2: 4 tabs, with potentially deep navigational paths on each tab.
In the opinion of some of your more experienced IOS developers, what would the general expectation of a user be with respect to saving application state between launches (i.e. after an app's been fully terminated and subsequently restarted)? I'm using Core Data and have all the data issues covered, but I'm concerned about the application's navigational tree. If the user had left the 1st tab on screen 3, the 2nd tab on screen 4, the third on screen 2, where he left the entry of a new record half-complete, and was, at the time of the app entering the background, working on the 4th tab on screen 3...do you think the average user would expect the application to remember all that the next time it launched? (My gut says yes, though I'm unsure for how long.)
If the answer is yes, can you suggest a general strategy for handling this (and, again, I'm talking about the navigational tree here, not Core Data stuff)? For example, if navigational controllers were used as the root view controller for each tab, it would be simple enough to record enough info about their navigational stacks to be able to restore them later. But what about things like popovers, alert/action sheets, or modal VCs created on the fly? Should each view controller record the state of its UI objects and, if so, what is the recommended 开发者_开发知识库way to do this?
I know a lot of this is up to the user, but I'm asking for the general perspective on these issues, i.e. the voice of experience.
It's pretty simple in principle, but it can get quite complex in practice, to go through your navigation hierarchy and storing stuff that can't be derived from the data model.
There's an open source implementation of this called DTResurectionKit. I also documented how I do it in my apps on my website. It's similar to (but simpler than) DTResurectionKit.
In the opinion of some of your more experienced IOS developers, what would the general expectation of a user be with respect to saving application state between launches?
The best way to think about this is to make sure the user never has to figure out why or how they got to where they are when the app first opens.
This depends completely on the type of app you have and the length of time since the last open. It sounds like you have a fairly complex drill-down app so I think it is definitely best to remember the navigation stack, within a pre-determined time frame. I use the three20 framework which does this automatically for me, but if you were to implement it, it would be something like this:
- If the user opens up in the past 24 hours, open to the exact spot the left off
- If the user opens within a week, open to the main "section" or area of the app they were in
- If the user opens after a week has past, open to the root screen.
Now of course, these values will differ based on your apps function and use cases, but you get the idea. By you making some broad assumptions about how people are using your app and when, you can increase the user experience by not shoving them so deep in your app when they won't remember how they got there.
As for implementation, it is all just data.. You dont need to serialize live objects to store the stack, just implement the data needed to recreate the state on the next launch. What you need to store is highly dependent on your own setup... mileage will vary. I use NSUserDefaults
to store all instance vars and the navigational stack through Three20. Check out TTNavigator for a great implementation.
I would suggest keeping the state of each tab view. Only at the "page" level. Don't worry about popovers or incomplete data entry (hopefully there's not too much interim state before you're saving it to your core data store.)
Like you said, it's easy enough to remember what tab you're on, and what controller you're navigated to in each tab. More isn't necessary.
It sounds like you've got it under control, but for the benefit of others: 1) when you change tabs, save "active tab", 2) when you navigate within a tab, save "active controller in tab", 3) when you launch the app, set the "active tab", 4) when you change tabs, set/confirm the "active controller in tab".
The reason for 4) is that the view/controllers for the tabs will be delayed in their loading, or perhaps never loaded. You don't want to set the "active controller in tab" for a tab that is not visible and may never be loaded into the app, it would just cause unnecessary loading. It will often happen (after the app has been loaded) that you don't need to change it because it's already in the correct state.
I think your time is better spent elsewhere. Of course, your app might be perfectly suited for this, but in our case data was partly online, could have gone stale, influenced view state in different navigation views in different tabs simultaneously, etc. etc. It's not an insurmountable challenge, but definitely hard and a huge time-sink.
We decided to spend our time on fixing the bugs and improving functionality. If you have to make the same kind of choice, I'm pretty sure which option your users would prefer. Particularly now that your app will survive a phone call in the background.
精彩评论