Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make my App run an NSTimer in the background?

I'm making a benchmark App for test purposes ONLY. I am not intending this to go to the App Store.

What I need is my NSTimer to continue running on the background using a UIBackgroundTaskIdentifier, save data to a Core Data db and finally push the data to a server (I'm using Parse), after a certain time interval, of course.

So basically, I haven´t found any questions which apply to my specific case. I set my NSTimer like so:

    UIBackgroundTaskIdentifier bgTask;
UIApplication  *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask]; 
}];

self.timer = [NSTimer scheduledTimerWithTimeInterval:self.localInterval target:self selector:@selector(updateCoreData:) userInfo:nil repeats:YES];

the method updateCoreData simply calls the Core Data class and makes the necessary insertions.

I've read about VoIP and the Music playing part, but don't know exactly which one would apply best for my case, nor how to implement them.

like image 927
LilDwarf Avatar asked Feb 09 '12 23:02

LilDwarf


People also ask

How do I let my iPhone play apps in the background?

Under the Capabilities tab, set the Background Modes switch to ON and select the “Audio, AirPlay, and Picture in Picture” option under the list of available modes. With this mode enabled and your audio session configured, your app is ready to play background audio.

Can a typical app run in the background IOS?

Overview. Typically, an app is in a suspended state when it's in the background. However, there are a limited number of background execution modes your app can support that enable it to run when in the background, such as playing audio, receiving location updates, or processing scheduled tasks.

How do you create a 60s countdown timer that prints out the seconds remaining every second Swift?

Underneath the timerLabel outlet create the following variables: var seconds = 60 //This variable will hold a starting value of seconds. It could be any amount above 0. var timer = Timer() var isTimerRunning = false //This will be used to make sure only one timer is created at a time.


2 Answers

I figured it out by myself, for anyone else with a similar problem, what I did was to first turn on the location update flag on your Info.plist file. To do this, you must add the Key called "Required Background Modes" on Xcode 4, then as a value, select "App registers for location updates"

I have a timer declared like so in my .h file:

NSTimer *silenceTimer;
@property (nonatomic, retain) NSTimer *silenceTimer;

Then on the .m file, I declared it like so:

UIBackgroundTaskIdentifier bgTask;
UIApplication  *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask]; 
}];
self.silenceTimer = [NSTimer scheduledTimerWithTimeInterval:300 target:self
selector:@selector(startLocationServices) userInfo:nil repeats:YES];

Finally, on the selector method, I made the following:

-(void)startLocationServices {
    [locationManager startUpdatingLocation];
    [locationManager stopUpdatingLocation];
}

This will create a timer that starts and immediately stops location services after 5 minutes. This will be enough for the app to stay alive indefinately, unless you kill the process.

like image 172
LilDwarf Avatar answered Sep 27 '22 19:09

LilDwarf


XCode 6.3.1, for iOS 8.3

There are big diffrences that I've encountered between the apps. behavior while plugged in to your Mac running XCode using debugger and the same apps. behavior while unplugged.

At current iOS version, 8.3, at most your app is allotted is 180 seconds to run in the background for finite long running task with an expiration handler.

No matter what you try, with your phone unplugged your app will be killed by the system in 180 seconds or earlier. I've done a significant amounts of tests and tricks to confirm this. See my post...

My NSTimer Post

Here is a neat way to tell how much time is left for your app to run before termination, keep in mind that you are not guaranteed this time.

NSTimeInterval backgroundTimeRemaining = [[UIApplication sharedApplication] backgroundTimeRemaining];

if (backgroundTimeRemaining == DBL_MAX)
{
    NSLog(@"background time remaining = undetermined");
}
else
{
    NSLog(@"background time remaining = %0.2f sec.", backgroundTimeRemaining);
}

Hope this helps your investigation. Cheers!

like image 39
serge-k Avatar answered Sep 27 '22 18:09

serge-k