I am triggering a background fetch by using the content-available flag on a push notification. I have the fetch and remote-notification UIBackgroundModes enabled.

Here is the implementation I am using in my AppDelegate.m:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    NSLog(@"Remote Notification Recieved");
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.alertBody =  @"Looks like i got a notification - fetch thingy";
    [application presentLocalNotificationNow:notification];
    completionHandler(UIBackgroundFetchResultNewData);

}

When the app is running in the background, it works fine. (The notification is received and the app triggered the "looks like i got a notification" local notification, as the code above should do).

However, when the app is not running and a push notification is received with the content-available flag, the app is not launched and the didRecieveRemoteNotification delegate method is never called.

The WWDC Video Whats New With Multitasking (#204 from WWDC 2013) shows this: enter image description here

It says that the application is "launched into background" when a push notification is received with the content-available flag.

Why is my app not launching into the background?

So the real question is:

Will iOS perform background tasks after the user has force-quit the app?

upvote
  flag
How are you checking whether the app launches in the background? – runmad
1 upvote
  flag
@runmad I log a bunch of crap in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions – Santa Claus
upvote
  flag
How are you logging it, just NSLog? You'll have to set the Launch to manual in your app scheme settings (see answer) – runmad
upvote
  flag
@runmad see comment on answer – Santa Claus
upvote
  flag
@HaimBenchimol Djd you get a response to your bug report? I haven't gotten around to filing my own bug report. – Santa Claus
upvote
  flag
@SantaClaus Is there some update on bug, which you submit about this problem? – Foriger
upvote
  flag
@Foriger I never got around to submitting a report. It would have been a documentation "enhancement" report, rather than a bug, since it is intended behavior. – Santa Claus
upvote
  flag
@SantaClaus any update ? – Omarj
upvote
  flag
@Omarj No. The only thing that may come of this would be a documentation clarification. I don't expect that the behavior will change, but I have no way of knowing. – Santa Claus

5 Answers 11

You can change your target's launch settings in "Manage Scheme" to Wait for <app>.app to be launched manually, which allows you debug by setting a breakpoint in application: didReceiveRemoteNotification: fetchCompletionHandler: and sending the push notification to trigger the background launch.

I'm not sure it'll solve the issue, but it may assist you with debugging for now.

screenshot

upvote
  flag
so this helped but the issue still exists – Santa Claus
upvote
  flag
Strange. I assume you've more than double-checked all the flash are set in your plist, etc.? – runmad
upvote
  flag
Also, i know i have everything set right because when the app is in the background, everything works perfectly. Its just when the app is not running at all that it doesn't. – Santa Claus
upvote
  flag
I wonder if a push notification launch-trigger is system-determined. For example, if iOS determines it's not a great time to launch the app right now it might postpone it until later. Perhaps try and close all running/background apps and see what happens? I am just guessing at this point :-/ – runmad
upvote
  flag
just tried that. Nothing happened, just like usual. I might ask on dev forums. – Santa Claus
upvote
  flag
Well...lucky you. Nobody found the answer besides me, and your answer was most helpful, so here is the bounty. Merry Christmas. – Santa Claus
upvote
  flag
Tested with iOS 7.1, as long as background refresh is ON in the settings app, the app will get woken up and the delegate methods will get called (even if the app is terminated or the device is rebooted). – jjxtra
upvote
  flag
As long as you don't swipe it out of the task list it will get woken up and re-launched (even if you reboot your device or the app is terminated due to memory) – jjxtra
upvote
  flag
U saved my life man ! I put control in didFinishLaunchingWithOptions:(NSDictionary *)launchOptions , if launchOptions is not nil, and launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationK‌​ey has an objects, i can understand push message received. Otherwise, launchOptions comes with nil argument. – Inna Kamoze
upvote
  flag
Is that related with the question? – Pedro Paulo Amorim
up vote 202 down vote accepted

UPDATE: It sounds like you can achieve this using the new PushKit framework, introduced in iOS 8. (See this answer).


Although this was not made clear by the WWDC video, a quick search on the developer forums turned this up:

https://devforums.apple.com/message/873265#873265 (login required)

Also keep in mind that if you kill your app from the app switcher (i.e. swiping up to kill the app) then the OS will never relaunch the app regardless of push notification or background fetch. In this case the user has to manually relaunch the app once and then from that point forward the background activities will be invoked. -pmarcos

That post was by an Apple employee so I think i can trust that this information is correct.

So it looks like when the app is killed from the app switcher (by swiping up), the app will never be launched, even for scheduled background fetches.


iOS 8 Update: The documentation has been clarified for iOS 8. The documentation can be read here. Here is a relevant excerpt:

Use this method to process incoming remote notifications for your app. Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running in the foreground, the system calls this method when your app is running in the foreground or background. In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a push notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.

1 upvote
  flag
For me adding the action in "didFinishLaunchingWithOptions" when launching options are not nil did the work. I have the same method here as in "didreceiveRemoteNotification" – harsh.prasad
upvote
  flag
@harsh.prasad that's interesting. The problem was that the app isn't launched when the app has been killed from the app switcher. – Santa Claus
3 upvote
  flag
The app needn't be shown in the app switcher if a silent push is received. It could be launched in the background without adding it to the app switcher, and be allowed to run and "do its thing" and then exit. Apps that stay active too long would be killed in the same way as they are already. – MindJuice
upvote
  flag
How did u do it @MindJuice?! Do you have a working example?! – davidOhara
upvote
  flag
@chrizstone I think he was just giving an example as to how Apple could handle this kind of thing. – Santa Claus
upvote
  flag
Ahh ok thanks...So you don´t have a solution yet?! – davidOhara
1 upvote
  flag
@chrizstone The solution is that this is intended behavior, and you can't do anything about it. – Santa Claus
upvote
  flag
Yes, Santa Claus is right. It was a hypothetical way it could be done. I hoped that there was a slim chance the Apple person might read this. :-) – MindJuice
upvote
  flag
Tested with iOS 7.1, as long as background refresh is ON in the settings app, the app will get woken up and the delegate methods will get called (even if the app is terminated or the device is rebooted). – jjxtra
upvote
  flag
@PsychoDad I didn't check with iOS 7.1. I guess I'll have to try that out! Thanks! – Santa Claus
upvote
  flag
@PsychoDad For me, it still doesn't work when the user terminates the app. As long as the user doesn't terminate the app, background fetch continues to function. – Santa Claus
upvote
  flag
@PsychoDad Yep. Figured that out when I posted this answer. – Santa Claus
upvote
  flag
@SantaClaus any update ?? – Omarj
upvote
  flag
What if you've started a background transfer service (BTS)? Will the app be woken up when the NSURLSession completes? Use case : 1)You start the BTS, 2)user taps home, 3)after a while the user kills your app from the app switcher, 4)your BTS completes. Will it fire the app up again ? – Yannick
upvote
  flag
iOS8 Update (Hopes not enforce NDA).Documentation is changed now. – Foriger
upvote
  flag
@Foriger Thanks for notifying me of that! I updated my answer. – Santa Claus
1 upvote
  flag
@JPK Uh, push notifications themselves aren't affected. It's just doing background tasks that won't work after it's been force quit. – Santa Claus
upvote
  flag
Thanks Santa Claus. I just realized the issue is only with the silent push notifications being able to download once the app is force closed. Since my app is having trouble with regular push notifications when force closed, I realize there is a problem with my app's code at this point. – SAHM
upvote
  flag
The notification opens my app but to a blank screen, then immediately closes it. – SAHM
upvote
  flag
@JPK Then it crashed. You need to take a look at how you are handling opening the app through a push notification. – Santa Claus
upvote
  flag
It was my own error. Thank you! – SAHM
upvote
  flag
Hey @SantaClaus,good info man, will this logic also work in iOS 7 or it is only for iOS 8. And is it fine to just check the background fetch from the options in xcode or to add some code? – Qasim Ali Khan
upvote
  flag
How to test non force-quit app launch? – ChikabuZ
upvote
  flag
iOS 10.Have someone tried Notification Service extension point? It look promising :) Haven't test it, just ask if someone have impressions? – Foriger
upvote
  flag
My observations withiOS 10 was silent notification reach to phone & perform tasks in foreground, background & sleep mode. However if a user power off the phone & turn back ON, the silent notification does reach to phone but do not execute any code in background. Problem explanation – Anish Kodeboyina

I've been trying different variants of this for days, and I thought for a day I had it re-launching the app in the background, even when the user swiped to kill, but no I can't replicate that behavior.

It's unfortunate that the behavior is quite different than before. On iOS 6, if you killed the app from the jiggling icons, it would still get re-awoken on SLC triggers. Now, if you kill by swiping, that doesn't happen.

It's a different behavior, and the user, who would continue to get useful information from our app if they had killed it on iOS 6, now will not.

We need to nudge our users to re-open the app now if they have swiped to kill it and are still expecting some of the notification behavior that we used to give them. I'm worried this won't be obvious to users when they swipe an app away. They may, after all, be basically cleaning up or wanting to rearrange the apps that are shown minimized.

2 upvote
  flag
That's exactly what we did (applicationWillTerminate), but I don't believe it gave the notification during memory purges, at least not on iOS 7. I did notice that it showed the notification right before a reboot for an OS upgrade, but that's so rare it didn't seem too bad. – snarshad
upvote
  flag
"On iOS 6, if you killed the app from the jiggling icons, it would still get re-awoken on SLC triggers. Now, if you kill by swiping, that doesn't happen." This does now happen, it was a temporary regression in an early version of iOS 7. – funkybro

Actually if you need to test background fetch you need to enable one option in scheme:

enabling bg fetch

Another way how you can test it: simulate bg fetch

Here is full information about this new feature: http://www.objc.io/issue-5/multitasking.html

The answer is YES, but shouldn't use 'Background Fetch' or 'Remote notification'. PushKit is the answer you desire.

In summary, PushKit, the new framework in ios 8, is the new push notification mechanism which can silently launch your app into the background with no visual alert prompt even your app was killed by swiping out from app switcher, amazingly you even cannot see it from app switcher.

PushKit reference from Apple:

The PushKit framework provides the classes for your iOS apps to receive pushes from remote servers. Pushes can be of one of two types: standard and VoIP. Standard pushes can deliver notifications just as in previous versions of iOS. VoIP pushes provide additional functionality on top of the standard push that is needed to VoIP apps to perform on-demand processing of the push before displaying a notification to the user.

To deploy this new feature, please refer to this tutorial: https://zeropush.com/guide/guide-to-pushkit-and-voip - I've tested it on my device and it works as expected.

9 upvote
  flag
Looks like to me you have to set your app as using VoIP. If you app isn't actually a VoIP app, won't it just get rejected during review? – duncanc4
5 upvote
  flag
Unfortunately, knowing the validation process by Apple, it would be logical that the application was rejected. – Kepa Santos
3 upvote
  flag
Used for VoIP. If not using VoIP for the user, this will greatly increase the risk of review rejection. – Chris
upvote
  flag
Looks like big providers are using this facility as an excuse to run stuff in the background and Apple is running a blind eye. Becoming Android one feature at the time. – TCB13

Not the answer you're looking for? Browse other questions tagged or ask your own question.