Saving and loading data when application enters / leaves background - ios

I am attempting to make my game persist its current state and reload it when a user exits or restarts the game. What I am struggling with, however, is how to actually get access to the objects at the right time. Here is the pseudo code for what I need, I just cant seem to get access to the right objects, am I doing this backwards or is this the correct way to do it?
So to reiterate, my problem here is getting access to the correct ViewControllers in order to save / load the data from disk.
My Navigation hierarchy is simple, ViewController > GameViewController (shown modally)
-(void)applicationDidEnterBackground:(UIApplication *)application
{
// Save current state to disk
// See if GameViewController (or GameView) is top controller (aka game in progress)
// If so then use NSKeyedArchiver to persist to disk
}
-(void)applicationDidBecomeActive:(UIApplication *)application
{
// Load current state from disk
// Use NSKeyedArchiver to load data from disk, if game is in progress then
// Find mainViewController, then show the game modal on top of it
// then populate the game data with the data from disk
}
Bonus question: Are these two functions the correct ones to be doing my saving / loading in?

lternatively you could set up a notification handler wherever you want/need in your code:
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(handleEnteredBackground:)
name: UIApplicationDidEnterBackgroundNotification
object: nil];

The correct way to solve this is to make use of the Model-View-Controller pattern (MVC) - as (almost) all good Cocoa iOS apps should:
First, ensure any data that you want to persist is stored in your model layer/object(s).
If the view controller's states change frequently, use the notification: UIApplicationWillEnterBackgroundNotification in the view controllers as the trigger to save the state to the model.
When the applicationDidEnterBackground: message is received in the app delegate, save the data in the model objects to the file system.
When the application wakes up or is restarted, load the file data back into the model and notify the view controllers via a custom notification so the view controllers know to restore their relevant states.
The app delegate shouldn't go around picking out bits of information from each view controller that it wants to save to the file system.

Related

Save UIViewController and display again if needed

I am trying to create a system where a user can open a UIViewController, close out of that ViewController, and return to the same ViewController if they closed it by accident. The UIViewController is populated with data from the internet (that changes frequently) and is a long scrolling UITableView. Currently when the user enters the same UIViewController again, the data is lost and must be re-downloaded, and their previous position is lost.
On the Android version of my app, I have a ViewPager as the main view, with the main pane being the left Fragment and the opened pane as the right Fragment. When the user opens the same "submission", the Fragment is not re-created and the user returns to the same screen, and if the user clicks a new submission, the old Fragment is deleted and a new one is loaded in its place. This allows for the state to be the same and the user can go back if they closed out of the pane by accident.
I think keeping a static version of the UIViewController would be bad practice and lead to memory issues down the road, but I cannot think of another way to implement this. Any suggestions would be appreciated.
You should read up on Apple's docs on restoring view controller state: https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/PreservingandRestoringState.html
Additionally, you will need to archive and unarchive the data being displayed in your view controller. Therefore you might want to implement the NSCoding protocol in your model classes. Once you've implemented NSCoder, you can use NSKeyedArchiver / NSKeyedUnarchiver to save and restore state for your view controller. Read up on NSCoding here: https://developer.apple.com/reference/foundation/nscoding
Finally the App Delegate sends out notifications when your app is about to terminate or move to the background. So in this class you will need to start the whole process of saving and restoring application state. Read up on UIApplicationDelegate here: https://developer.apple.com/reference/uikit/uiapplicationdelegate

How can I make a good use of didFinishLaunchingWithOptions in Appdelegate

I want to extract some data from the server or database, now I'm confusing if I have to put the extracting code in didFinishLaunchingWithOptions() function or put the code in viewdidload() function in the first viewcontroller. What's the execution efficiency of both methods?
It depends on your requirement. If you want the data before actually going to a viewController then you can extract it in didFinishLaunching WithOptions. But if you want the data for only viewController then its good practise to extract it when you are on that viewController i.e in viewDidLoad of that viewController.
If you fetch data over the network, I'd definitely recommend not to use didFinishLaunchingWithOptions. Any blocking code in this method will prevent the app's UI from loading, so you can't even display a "Please wait" message to the user. Also, iOS will kill your app if didFinishLaunchingWithOptions blocks for too long (I think the timeout is about 10 seconds).
So either perform the loading in your main view controller, or run it asynchronously in a background queue — in this case, you can of course also put the code in didFinishLaunchingWithOptions.

Objective-c iOs Autosaving information when exiting a view

I am programming an ios app and would like to save information on exit of the view. I know how to go about saving the actual information but I'm not sure where I should put the code.
In android, there are methods like onPause() where I can run the save code to capture whenever someone leaves an activity. Is there something in obj-c like that?
You can add your logic for saving the state of the view in viewWillDisappear
I guess you have not gone through the View Life Cycle, here s one nice image which has captured the view life cycle events.
Reference : http://rdkw.wordpress.com/2013/02/24/ios-uiviewcontroller-lifecycle/

A good way to temporarily store data for multiple views in iOS

I have a main view controller that contains a variable amount of buttons (usually 6). When one of those buttons is tapped, I query a server to fetch a stream of information with roughly 40 items, and then I pop that data into a tableview. The stream is analogous to a Twitter stream, and so I can't keep the data on the device since it's always changing.
I can always expect a delay when pressing a button that I haven't pressed before cause the data has never been loaded onto the device. I want to know how I should temporarily store that data. That way I can immediately load the tableview the second time I press the button (from the main view) while the new data is loading.
Let me know if I'm being too abstract.
If you don't want to get into Core Data, I'd say try to serialize out your data into a flat file. Then using NSFileManager, store this file in the application Cache directory. Then when the application launches again, read in from this file before requesting from the network.
Augie's answer to pass this data between view controllers is the way to go during the lifetime of the app. This Cache file would only be necessary when the application terminates and re-launches.
in a nsarray property of your vc and use that array as your tableview datasource
You could simply use an NSArray property , but if you also want the data to be persistent after a relaunch of the app, I would advise you to use CoreData.

iOS 5 - Where should NSURLConnection go for an app with multiple views?

I am writing an app that has various views; but all of them basically need an access to a connection so they can retrieve data from a server.
Now I was kinda lost about where should I put the code to initialize the connection and retrieve the data.
IF i put it in the viewDidLoad; the connection will be created and the data retrieved every time that the user switch view (I have a tab bar to switch between views); and this is not hat I want (for obvious reasons, the data should be retrieved only if the user tap on the refresh button, and the connection should not be created every time that the view switch).
Where should I put the method that creates the connection and retrieve the data, so I can access this data from anywhere in the app (more specifically the other views of the app; each view show different parts of the data downloaded from the server) and avoid to overload the user and shrink the battery life with continuous connections and data retrieval?
Thanks in advance!
(for obvious reasons, the data should be retrieved only if the user
tap on the refresh button, and the connection should not be created
every time that the view switch).
If you only want to sync the data in response to the user tapping a button, then create a method
- (IBAction)syncData;
and in Interface builder connect the touchUpInside event of the button to the syncData method.

Resources