3

I use this code to execute function every X minutes:

- (void)executeEveryOneMinute
{
    [self myFunction];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        [self executeEveryOneMinute];

    });
}

And it works when app is in foreground.
But when app goes background it doesn't work anymore.
When I return app to foreground again it execute function once.
And continue to call function every minute again.

So how to make this to work in background too?

1110
  • 7,829
  • 55
  • 176
  • 334

4 Answers4

5

See the Background Execution and Multitasking section of the iOS App Programming Guide: App States and Multitasking for a discussion of the possibilities. You can, for example, keep the app running in the background for a few minutes in order to complete some finite length task. Or you can continue to run the app in the background for a longer period of time if it's performing one of a very particular list of functions (quoting from the aforementioned document):

  • Apps that play audible content to the user while in the background, such as a music player app
  • Apps that record audio content while in the background.
  • Apps that keep users informed of their location at all times, such as a navigation app
  • Apps that support Voice over Internet Protocol (VoIP)
  • Apps that need to download and process new content regularly
  • Apps that receive regular updates from external accessories

Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of those services. Declaring the services lets the system know which services you use, but in some cases it is the system frameworks that actually prevent your application from being suspended.

But, a fundamental design principle in iOS battery/power management is that random apps can not (and should not) continue to run in the background. If you share what precisely you're trying to do (namely, what precisely you're doing inside that executeEveryOneMinute method), though, we can offer counsel on how to achieve the desired effect, if possible.


If you're trying to have an upload continue in the background, in iOS 7 and greater, you should consider using NSURLSession with a background session configuration ([NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; there is a similar method in iOS 8). This will continue to attempt to upload (automatically, without further intervention on your part) not only after your app has left the foreground, but even after the app is terminated (e.g. due to memory pressure or a crash). AFNetworking offers a NSURLSession-based class, AFURLSessionManager, which supports this (though it's not NSOperation-based). This way, you enjoy background uploads, but conforms to Apple guidelines on background operation, notably with less dramatic battery impact than retrying yourself every 60 seconds.

I'd suggest you refer to the latter part of WWDC 2013 video What’s New in Foundation Networking, which demonstrates this process (they're doing a download, but the idea is the same for uploads).

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Here what I trying to do. I have some data in local db (on phone) and must ensure that I send them to server. I am using AFNetworking to pass data to server. If user try to upload data first time but FAILS (no internet for example, or server is down) I save it in local db and I need to try to send it to server every few minutes until is succeeds. I don't know if there is better way for doing this. – 1110 Jun 12 '14 at 09:17
  • @1110 iOS7 offers background upload capabilities, which does this for you. AFNetworking also offers a `NSURLSession` based class, [`AFURLSessionManager`](http://cocoadocs.org/docsets/AFNetworking/2.0.0/Classes/AFHTTPSessionManager.html). See addendum to my answer. – Rob Jun 12 '14 at 09:28
0

Timer works on Main thread. When application goes into background, its timers become invalid. So, you cant do the same when application goes into background.

Apurv
  • 17,116
  • 8
  • 51
  • 67
0

You can't do this with help of timer as it will be invalidated in background. You can try check this.

Rushi
  • 4,553
  • 4
  • 33
  • 46
0

You should use background tasks to achieve what you want

UIApplication*    app = [UIApplication sharedApplication];
task = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:task];
        task = UIBackgroundTaskInvalid;
    }];
// Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task.
        NSLog(@"Started background task timeremaining = %f", [app backgroundTimeRemaining]);
        if (connectedToNetwork) {
            // do work son...
        }

        [app endBackgroundTask:task];
        task = UIBackgroundTaskInvalid;
    });
channi
  • 1,028
  • 9
  • 16