4

Scenario is:

Application has on main run loop that runs every 5 min. When app is backgrounded, the timer is not invalidated.

On foreground after waiting a bit (say 10 min), the timer immediately fires twice. I'm unclear as to what the defined behavior here should be (if any) other than on background, the timer is paused/suspended along with the app.

It seems to me that when the app is foregrounded, the timer actually looks at the elapsed time since background, determines the number of times it should have fired in between, and fires them all. I observed this scenario happening both on iOS 7 simulator and iOS 7 iphone.

Google search didn't turn up much info on this topic. Any ideas/pointers?

Update: Clarification - my question is what is the behavior for NSTimer when the application is backgrounded and then foregrounded again, assuming the timer is not invalidated/nil-ed on background, and a new timer is not created on foreground.

Code sample (code is bit old - pre ARC days):

@implementation ReportHandler {
    NSTimer *_reportTimer;
}

- (id)init
{
    if (_reportTimer == nil) {
        _reportTimer = [[NSTimer  timerWithTimeInterval:5*60 target:self selector:@selector(didFireReportTimer:) userInfo:nil repeats:YES] retain];
        [[NSRunLoop mainRunLoop] addTimer:_reportTimer forMode:NSDefaultRunLoopMode];
    }
}

- (void)didFireReportTimer:(NSTimer *)timer {
   // send report over network here, timer is not invalidated here
}

There are no background/foreground handlers either here or in the app delegate dealing with this timer.

user3072558
  • 723
  • 1
  • 6
  • 11
  • The question is not clear to me. – KudoCC Jan 16 '14 at 02:56
  • Are you starting a new timer when the app comes to the foreground? Are you sure it is the same timer firing? Perhaps you could post code and it would be clear to others. – HalR Jan 16 '14 at 03:53
  • NSTimer is not guaranteed to fire while in background. You could use an independent time check with your current setup to make sure your fireFunction does not get called back to back. Also take a look at this previous Q&A http://stackoverflow.com/questions/8415870/scheduled-nstimer-when-app-is-in-background – sangony Jan 16 '14 at 19:22
  • I realize that the way to get deterministic behavior is to invalidate the timer on background and then restart on foreground. My question was whether the behavior on background/foreground was documented/known, or undefined. My searches seem to suggest undefined and I haven't found any evidence to the contrary. – user3072558 Jan 16 '14 at 22:36

1 Answers1

2

It seems to me that when the app is foregrounded, the timer actually looks at the elapsed time since background, determines the number of times it should have fired in between, and fires them all. I observed this scenario happening both on iOS 7 simulator and iOS 7 iphone.

That is a correct description of the behavior of NSTimer and the run loop. When your app is suspended it won't fire (by default, when you background it; but if you start a background task, it will fire as normal while the task is running).

jmah
  • 2,216
  • 14
  • 16
  • 1
    You answer is correct, but the "determines the number of times it should have fired in between, and fires them all is different of described on the NSTimer documentation: "If the firing time is delayed so far that it passes one or more of the scheduled firing times, the timer is fired only once for that time period; the timer is then rescheduled, after firing, for the next scheduled firing time in the future". It will fire immediately, but only once. – Roberto Ferraz Aug 07 '14 at 08:51