How keep NSTimer when application entering background?

19,992

Solution 1

You need to read the guide on how to run tasks in the background:

Background Execution and Multitasking

Here is my applicationDidEnterBackground for one of my apps. When I put it to the background, it does some disk cache maintenance:

- (void)applicationDidEnterBackground:(UIApplication *)application {

//As we are going into the background, I want to start a background task to clean up the disk caches
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) { //Check if our iOS version supports multitasking I.E iOS 4
    if ([[UIDevice currentDevice] isMultitaskingSupported]) { //Check if device supports mulitasking
        UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance

        __block UIBackgroundTaskIdentifier background_task; //Create a task object

        background_task = [application beginBackgroundTaskWithExpirationHandler: ^{
            [application endBackgroundTask:background_task]; //Tell the system that we are done with the tasks
            background_task = UIBackgroundTaskInvalid; //Set the task to be invalid
            //System will be shutting down the app at any point in time now
        }];

        //Background tasks require you to use asyncrous tasks
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            //Perform your tasks that your application requires                

            //I do what i need to do here.... synchronously...                

            [application endBackgroundTask: background_task]; //End the task so the system knows that you are done with what you need to perform
            background_task = UIBackgroundTaskInvalid; //Invalidate the background_task
        });
    }
}

}

Solution 2

From the Apple docs:

Implementing Long-Running Background Tasks For tasks that require more execution time to implement, you must request specific permissions to run them in the background without their being suspended. In iOS, only specific app types are allowed to run in the background:

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

Unless your app falls into one of these categories (and it sounds like it doesn't), then it won't be able to run while in the background.

Solution 3

The iOS App Programming Guide lists the activities for which your app is allowed to remain active in the background. If you plan on distributing your app through the app store, your app will have to perform one of the listed activities. If you're just writing something for yourself, you might be able to piggyback your functionality on one of the allowed activities.

Share:
19,992
UIChris
Author by

UIChris

Updated on July 29, 2022

Comments

  • UIChris
    UIChris almost 2 years

    I'm here because a didn't find any solutions for my issue :(

    I'm doing an simple application in which i have to send (by socket) some informations to a server (like GPS l/L, accuracy, Battery level, etc).

    The current code works fine when application is in foreground.

    myTimer = [NSTimer scheduledTimerWithTimeInterval: 2.0 target:self
                                                      selector: @selector(sendPosToServer:) userInfo:nil repeats: YES];
    myTimer2 = [NSTimer scheduledTimerWithTimeInterval: 3.0 target:self
                                                      selector: @selector(sendBatteryToServer:) userInfo:nil repeats: YES];
    myTimer3 = [NSTimer scheduledTimerWithTimeInterval: 5.0 target:self
                                                      selector: @selector(sendResToServer:) userInfo:nil repeats: YES];
    myTimer4 = [NSTimer scheduledTimerWithTimeInterval: 5.0 target:self
                                                      selector: @selector(sendQResToServer:) userInfo:nil repeats: YES];
    myTimer5 = [NSTimer scheduledTimerWithTimeInterval: 3.0 target:self
                                                       selector: @selector(sendPrecisionToServer:) userInfo:nil repeats: YES];
    

    All thoses methods are called.

    But when application enter in background, all timer are invalidate... I've read that iOS automatically stop timers.. I'm looking for a way to call methods and send datas when application is in background..

    I need your help :)

    Thanks to everyone !!

  • UIChris
    UIChris over 12 years
    Ok. i will distribute it. I'm sending information to server about GPS data. So i think that's greats right ? "Communicating with an External Accessory"
  • Caleb
    Caleb over 12 years
    "External accessory" means something connected to the device, not some server on the net. So if you're getting the GPS data from some GPS receiver that communicates via bluetooth, for example, then the external accessory option might work. If you're getting the data from the device's own GPS receiver, use the location service instead. The device will tell you when the location changes. You'll have to change your approach since you can't update the server at fixed intervals.
  • UIChris
    UIChris over 12 years
    I'm asking to my app for GPS locations. So it does with "Apps that keep users informed of their location at all times, such as a navigation app" ?
  • UIChris
    UIChris over 12 years
    =/ Ok. I'm prety bad in IOS dev. I understand what you mean but i don't know how perform it
  • UIChris
    UIChris over 12 years
    With this part of code, methods are called. It work fine, but could I distribute it ?
  • Rok Jarc
    Rok Jarc over 12 years
    @user1147981: just in case if you're intending to write this as some kind of 'fleet management' app you should know that it will not pass the review (App Store Review Guidelines)