How to Run Nstimer in Background Beyond 180Sec in iOS 7

iphone - NSTimers in background

I have a similar app design and was stuck on the same thing. What I found somewhere on the internet is adding this type of statement applicationDidEnterBackground:

    UIBackgroundTaskIdentifier locationUpdater =[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:locationUpdater];
locationUpdater=UIBackgroundTaskInvalid;
} ];

This tells the os that you still have things going and not to stop it.

I have my timer attached to this function

 //this is a wrapper method to fit the required selector signature
- (void)timeIntervalEnded:(NSTimer*)timer {
[self writeToLog:[NSString stringWithFormat:@"Timer Ended On %@",[NSDate date]]];
[self startReadingLocation];
[timer invalidate];
timer=nil;
}

I set the timer in my my location manager delegate methods.

I feel your pain. I found that these things were super finicky. This is what worked for me. I hope it helps. I have found that there isn't any really restrictions in what you can do in the background.

Scheduled NSTimer when app is in background?

You shouldn't solve this problem by setting a timer, because you're not allowed to execute any code in the background. Imagine what will happen if the user restarts his iPhone in the meantime or with some other edge cases.

Use the applicationDidEnterBackground: and applicationWillEnterForeground: methods of your AppDelegate to get the behavior you want. It's way more robust, because it will also work when your App is completely killed because of a reboot or memory pressure.

You can save the time the timer will fire next when your App is going to the background and check if you should take action when the App comes back to the foreground. Also stop and start the timer in this methods. While your App is running you could use a timer to trigger the update at the right moment.

Running an already running NStimer in Background

Unless you enable one of the Background modes, it is not gonna work.

Why?

You have around 10 minutes of background execution after this the timer is stopped by ios.

The timer will not fire after app is locked (iOS7), since ios suspends the foreground app and bgTask will not get fire again.

There is some workarounds, consider to check below

// NSTimer run when app in background

[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
loop = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(Update) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:loop forMode:NSRunLoopCommonModes];

Anotherway check this NSTimer in Background

Is NSTimer expected to fire when app is backgrounded?

NSTimer is going to fire whenever the main runloop is running. Apple makes no promises that I know of to unschedule timers or to prevent the main runloop from running. It's your responsibility to unschedule your timers and release resources when you move to the background. Apple isn't going to do it for you. They may, however, kill you for running when you are not supposed to or using too many seconds.

There are many holes in the system that will allow an app to run when it isn't authorized to. It would be very expensive for the OS to prevent this. But you cannot rely on it.

Is NSTimer expected to fire when app is backgrounded?

NSTimer is going to fire whenever the main runloop is running. Apple makes no promises that I know of to unschedule timers or to prevent the main runloop from running. It's your responsibility to unschedule your timers and release resources when you move to the background. Apple isn't going to do it for you. They may, however, kill you for running when you are not supposed to or using too many seconds.

There are many holes in the system that will allow an app to run when it isn't authorized to. It would be very expensive for the OS to prevent this. But you cannot rely on it.

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

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.

NSTimer behavior in background (addTimer:, beginBackgroundTaskWithExpirationHandler:)

Yes, running the app through the debugger will keep it alive when it otherwise would be terminated after 3 minutes. So, you obviously cannot rely upon that feature in a production app.

No, attempts to keep the app alive beyond this period of time are not legitimate (unless you have requested proper background operation because your app has legitimate and compelling need for background operation, e.g. it is a music player, VOIP, a navigation app, etc.). Apple is likely to reject any such app that is not in conformance with section 2.16 of the App Store Review Guidelines.

See the Background Execution chapter of the App Programming Guide for iOS for a fuller discussion of valid background operation.



Related Topics



Leave a reply



Submit