Executing Timer in background in iOS

Timer dispatch sources generate events at regular, time-based intervals. You can use timers to initiate specific tasks that need to be performed regularly. For example, games and other graphics-intensive applications might use timers to initiate screen or animation updates. You could also set up a timer and use the resulting events to check for new information on a frequently updated server.

All timer dispatch sources are interval timers—that is, once created, they deliver regular events at the interval you specify. When you create a timer dispatch source, one of the values you must specify is a leeway value to give the system some idea of the desired accuracy for timer events. Leeway values give the system some flexibility in how it manages power and wakes up cores. For example, the system might use the leeway value to advance or delay the fire time and align it better with other system events. You should therefore specify a leeway value whenever possible for your own timers.

If you tried to execute NSTimer in the background thread, it would fail.

[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideManual) userInfo:nil repeats:NO];

You can execute the above using run loops to make it work.

RunLoop.current.add(self.countdownTimer, forMode: .common)
RunLoop.current.run()

But the more optimal way would be run it as show below. For this, we need to create a dispatch source as shown below

-(dispatch_source_t) createDispatchTimer:(uint64_t)interval leeway:(uint64_t)leeway queue:(dispatch_queue_t)queue block:(dispatch_block_t)block
{
   dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
   if (timer)
   {
      dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval, leeway);
      dispatch_source_set_event_handler(timer, block);
      dispatch_resume(timer);
   }
   return timer;
}

Once the dispatch source has been created, we can call it.

[self presentViewController:_mediaBrowser animated:animate completion:^{
		dispatch_queue_t queue = dispatch_queue_create("com.queue", 0);
		timer = [self createDispatchTimer:1ull * NSEC_PER_SEC leeway:1ull * NSEC_PER_SEC queue:queue block:^{
			[self shouldContinueTimer];
		}];
	}];

Once the timer has been set, we can cancel it in the helper method.


-(void) shouldContinueTimer
{
	if (cancel)
	{
		dispatch_source_cancel(timer);
	}
}

When a computer goes to sleep, all timer dispatch sources are suspended. When the computer wakes up, those timer dispatch sources are automatically woken up as well. Depending on the configuration of the timer, pauses of this nature may affect when your timer fires next. If you set up your timer dispatch source using the dispatch_time function or the DISPATCH_TIME_NOW constant, the timer dispatch source uses the default system clock to determine when to fire. However, the default clock does not advance while the computer is asleep. By contrast, when you set up your timer dispatch source using the dispatch_walltime function, the timer dispatch source tracks its firing time to the wall clock time. This latter option is typically appropriate for timers whose firing interval is relatively large because it prevents there from being too much drift between event times.

Leave a Reply

Your email address will not be published. Required fields are marked *