NSURLConnection and multitasking in iOS - cocoa-touch

I'm using NSURLConnection to download resources asynchronously in iOS. (They are large-ish PDF files, so it takes some time on a slow connection.)
Now I'm updating my app from iOS 3 to iOS 4. As my app is none of location-aware, voip, and background music, I guess I need to do something.
My question is, then, what happens to the NSURLConnection currently running? Is it suspended and magically resumed when the app comes back to the foreground, or is it outright killed? If it is the latter, what is the standard strategy to resume it automatically later? Is there a open-source subclass of NSURLConnection which automatically does that?

You can start a task that will run for at most 10 minutes. Look at using the beginBackgroundTaskWithExpirationHandler: API for this purpose. Just be aware, if your task takes too long, it will be killed by the OS.

The NSURLConnection is indeed suspended and started again when the app enters the foreground. Just make sure you kill the connection if the app moves from suspended to not running like so:
- (void)applicationWillTerminate:(UIApplication *)application {
if (self.downloadConnection != nil){
[self.downloadConnection cancel];
}
}

Related

ios 7 : didreceiveremotenotification fetchcompletionhandler not getting called when app kept in background for over night testing

I have used VoIP and remote notification as background modes.
I kept my application idle in background for overnight testing.
I have written following code in applicationDidEnterBackground
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
NSString *message = #"voip keep alive timeout executed....";
NSLog(#"%#",message);
[Logger addEntry:CAT_ML_CORE andSubCategory:SUBCAT_DEBUG andMessage:message];
}];
}
after 1 day keeping application idle in background I found "voip keep alive timeout executed...." got printed in my logs.
This indicated that my app is alive.
But when I send push notification to my app "didreceiveremotenotification fetchcompletionhandler" method doesn't get called.
Which is contradictory to the statement made by Apple "Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running, the system calls didreceiveremotenotification fetchcompletionhandler method regardless of the state of your app. If your app is suspended or not running, the system wakes up or launches your app and puts it into the background running state before calling the method."
Can someone please tell me why this is happening?
Make sure your APNS payload has "content-available"
content-available - number - Provide this key with a value of 1 to indicate that new content is available.This is used to support Newsstand apps and background content downloads.
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html

Cancel Local Notification When app goes to Suspended state.(removed from background)

I am using Local notification in my application.it is working fine in foreground and background.
Now, What i need,if i remove my app from background then i want to cancel all notification
before that.
so , there are not any method are calling in appdelegate when i am going to remove my app from background, obviously it is going to Suspended state so no method is going to called.
so is there any other way to do this ?
Thanks in advance...
Considering your app is not one of the supported background execution modes, like audio, VoIP, or navigation,
Your app will generally never see willTerminate, because the system generally only terminates your app once it's already suspended (in the background). Once your app is suspended, it gets no further chance to act, so there's no callback for that.
The didEnterBackground delegate message or notification should be considered your last chance to clean things up or save state before possible termination.
Here and here are good overview of the application lifecycle notifications & delegate messages on iOS 4.0 and later.

NSThread halting when lost focus

I have a a few threads that needs to run constantly or be locked at my disposal. When I lock the phone or swap applications the thread seems to halt until the application is back in focus.
I have a class Worker that is a sub class of NSThread. There is a method called start which is called by the firstViewController that creates the Worker object.
//method start
[self performSelectorInBackground:#selector(run) withObject:self];
What do I need to do to make my thread run all the time, rather than only running while in focus?
Thanks :)
When your app enters the background, all threads as suspended - unless you've configured your application to use multi-tasking, and your work is being done using the multi-tasking methods. This is detailed at Apple developer.
In short, you basically can't have a thread running constantly in the background on iOS if you want to be accepted in the App store, unless you're a navigation or VOIP application. You can have a thread continue to run for around 10 minutes after you enter the background, but that's it.

App freeze while Schedule LocalNotifications in background

- (void)applicationDidEnterBackground:(UIApplication *)application
{
for (int i =0; i<30; i++){
//add a local notification and schedule it
}
}
when app switch to background, these codes will freeze app in a while.
There's no document about UIApplication is thread safe or not.
After a long time test I found most time execute LocalNotification on background works well. but some times it just crash our app.
So it seems like all the class with 'UI' prefixed are not thread safe and you should never invoke there's methods on another thread.
And my solution is reduced the number of LocalNotification, it still freeze app in a bit, but we thing we can accept this little freeze.
By default, application processing freezes when the app goes to the background. The execution continues from the same statement where it left when the app comes back to the foreground. To execute code in the background, you have to surround it in the beginBackgroundTaskWithExpirationHandler block.
Have a look at the section Completing a Finite-Length Task in the Background at http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/BackgroundExecution/BackgroundExecution.html.

Run repeating timer when applicationDidEnterBackground

My goal is to run a repeating timer every five seconds if and only if the application is running in the background. I've tried a couple of ideas, but they don't seem to work.
Idea 1: Doesn't run even once.
- (void)applicationDidEnterBackground:(UIApplication *)application {
[NSTimer scheduledTimerWithTimeInterval:(5.0/5.0) target:self selector:#selector(check_expiry) userInfo:nil repeats:YES];
}
Idea 2: Runs every five seconds, but I can't seem to stop the loop.
- (void)applicationDidEnterBackground:(UIApplication *)application {
counter = YES;
while (counter) {
sleep(5);
[self check_expiry];
}
// Counter is set to NO in willEnterForeground and didBecomeActive, but this loop continues to run due the sleep();
}
How can I get this loop to run properly?
Thanks!
When an application "enters the background" in iOS, that's not like normal operating systems, where it continues to run. The application enters a suspended state. It doesn't keep running; only application state is preserved, and even that's not guaranteed - if the device is running low on memory, iOS will happily terminate your application to give the memory to the active application. If you attempt to block in applicationDidEnterBackground:, like you are doing with sleep(), iOS will simply terminate your application for not returning from that method promptly.
Your application is woken up periodically if it's configured for background processing GPS events, VOIP, etc., but abusing those just to get your app to run will stop you from getting App Store approval.
This is all covered in The iOS Application Programming Guide.
For anyone looking for a workaround, I merely created a system that schedules timers at a later date when the applicationDidEnterBackground: and changed/cancelled them when they were edited/deleted. Information on timer scheduling was stored in a local dictionary.