IOS: Is it possible preserve the State of UIViewController in Background - ios

Am developing an IOS app. Where i need to make some images upload to server. Am using NSURLSession and uploadTaskWithRequest to do this. Every thing is working fine in normal way. My requirement user wants to store some post with more than 10 images in app using database SQLLite. And later show all the stored posts in UITableView with button for each UITableViewCell. When user tap on each button it should start uploading each POST to server. So I thought i should persist my UIViewController in AppDelegate so the process of uploading should not be killed when user go to another view controllers.
My Problem: When user close the app the process is in which UIViewController POST uploading is Stoping. So i would like to know how to keep my UIViewController live even in app go close or go into background.
Is there any better way to fulfill my requirement.

Here are some better ways!
Use a singleton. In my apps, I'll usually create a class called "DataHandler" that handles all of the NSURLSession/CoreData/etc stuff so all I have to do is
[DataHandler uploadImages:images];
and when I need the information back I'll call
self.tableData = [DataHandler lastUploadedImages];
This way I don't have to worry if my view controller is still alive.
Have the AppDelegate do the NSURLSession stuff. You already know the AppDelegate is persisted so why not just have that guy do it! Here is an example:
UIApplication *sharedApplication = [UIApplication sharedApplication];
AppDelegate *appDelegate = [sharedApplication delegate];
// this is the method you would add to your AppDelegate. Make sure to
// import your AppDelegate's header file so your ViewController can
// call the method.
[appDelegate uploadImages:images];

Related

Saving and loading data when application enters / leaves background

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.

Howto react to local notification in the currently running view

I have a web app, that is running partly in background mode (at least for the time, iOS does allow that).
When an event occurs inside it, I ifre a local notification.
When the user clicks on it, the app comes back to the foreground, but I want to call some javascript function inside the web app.
How do I call a function inside my view controller from the app delegate's
application:didReceiveLocalNotification method?
Assuming myViewController as the rootViewController you can use:
AppDelegate *delegate = (AppDelegate *) application.delegate;
[delegate.window.rootViewController launchJavascriptMethod];

iOS, use AppDelegate in InterfaceBuilder, two instances created

In an iOS application I implemented some application logic in the AppDelegate.
Several view controllers etc. need to call the AppDelegate, so i placed the AppDelegate in Interface Builder and gave the ViewControllers an IBOutlet AppDelegate* and drew a link to it.
In the app I see now that there seem to be two instances of the AppDelegate created, one that is called and that gets all the notifications and one that is linked to the ViewControllers.
So i changed my app to use in the ViewControllers:
app_del = (AppDelegate*)[[UIApplication sharedApplication] delegate].
Then I'm calling this appDelegate. But this also is a different instance than the one that gets the notifications. Can anybody explain why?
Can anybody tell me what is going wrong? My suspicion from googling is that the iOS creates the AppDelegate instance and Interface Builder does not know about that one and creates another one? Is that correct?
Can anybody give me some hint on how to best create/plan instances in Interface Builder and in what order they are created in application at startup and in what notification I can rely that they are all created?
Thanks for any hints,
Torsten.
Your suspicion is correct. iOS creates an instance of your application delegate when launching your app, this instance is the one that is registered to receive all of the delegate events and so forth. See here.
Anything you add in to a xib or storyboard will be a new instance, and will not work.
To obtain a pointer to the application delegate, use this method:
[[UIApplication sharedApplication] delegate];
There is a school of thought that says you shouldn't overuse the application delegate as a conveniently available global data or method store, but that is outside the scope of this answer.

App delegate features in viewcontrller - Facebook

I have a sample code with a header and an implementation file and the two appDelegate files. I would like to add what the project does to my app. The first two files are a ViewController file, so I just need to drag it in, but the other two are AppDelegate, and I obviously can't have two app delegate. But in the case of this sample app the app delegate is used as a proper viewcontroller, because in the .m file of the UIViewController file, there is this code:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
Since the AppDelegate doesn't implement methods such as applicationWillBecomeActive:, how can I transform the file into a UIViewController file? What do I need to change in the code above to call the controller, instead of the Delegate (my AppDelegate will so remain untouched).
The code is on GitHub
This is what I have done (the code needs the Facebook API to be included). Go on the download tab and download Archive.zip and AppDelegate.zip: https://github.com/Alexmitico45/FacebookRequests/downloads
Basically the controller ContactFBSViewController is linked the a viewcontroller in the storyboard.
AppDelegate is the singleton that implement the protocol UIApplicationDelegate, because so you can't duplicate it, it must be unique.
You can create your own singletons to store the info available all over your app.
You can google "objective-c singleton" and get some good link to do it

Show MBProgressHUD on iPhone app's splash screen while Core Data store is migrating to new version?

If my iPhone app needs to update the Core Data database, I would like to show an MBProgressHUD view to users while my iPhone app is loading, so they know that it's working and not hanging. How might I go about adding an MBProgressHUD to the splash screen while the data store is migrating? Normally I would attach it to the UIViewController's view, but the splash screen is under the app delegate. Is this possible to do?
No it is not possible to overlay anything over the splash screen as it's static.
You could, however, delay the intensive process for a bit until the app loads, then create a fake splash screen with the progress indicator while the intensive stuff goes on in a background thread.
You could create a #define macro in your application delegate header file (or in a "globals" header), like so:
#define MyAppDelegate [[UIApplication sharedApplication] delegate]
Then, when you want access the application delegate property, you can do so like this anywhere in your application you have imported that header (or the globals header):
MyAppDelegate.property = foo;
[[MyAppDelegate property] bar];
This may help you manage your progress view at any point in the app's life.
EDIT
sudo rm -rf is correct that you can't do work during the splash screen. But you can start your progress view in the app delegate's -applicationDidFinishLaunching: method, and then launch work on a background thread. Once your background thread's work is finished, have a callback dismiss the progress view.

Resources