5

I have created Application which runs NSTimer in Background. I used the Location manager to run the NSTimer in background,

I used below link to run NSTimer in background,

How do I get a background location update every n minutes in my iOS application?

This approach works fine in iOS 6 but not works on iOS 7. My Application crashes after some time while Application in background on iOS 7.

Please let me know if any different approach to run the NSTimer in background.

Thanks in advance.

Community
  • 1
  • 1
  • possible duplicate of [NSTimer in background](http://stackoverflow.com/questions/18124039/nstimer-in-background) – bneely Sep 26 '13 at 06:49
  • 2
    Change your design - why do you need a timer in the background? – Wain Sep 26 '13 at 06:59
  • 1
    @Wain : i get some the GPS data at particular time so i used the NSTimer. like i wan't scenario like keep the GPS data at 3.30PM and Stop the collect the GPS data at 6.30. System kills the App. in Background. so i just ping the location manager every 5 minute to keep the Timer alive. –  Sep 26 '13 at 07:11
  • Add some code to show how you manage your timer and background expiration. Apple changed the background task times. – Léo Natan Sep 26 '13 at 07:28
  • 1
    Why not check the time when you receive a GPS update and decide whether you need to stay registered for updates or disconnect? – Wain Sep 26 '13 at 10:06

4 Answers4

5

In iOS7, there is a new mode for periodic data fetch. Add the fetch background mode to your app, and in your application delegate, pass an interval to - [UIApplication setMinimumBackgroundFetchInterval:. Your app's delegate will start receiving calls to application:performFetchWithCompletionHandler: once the app is in the background.

More information here: https://developer.apple.com/library/ios/documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:performFetchWithCompletionHandler:

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
  • Further to this, running arbitrary code under the guise of a location enabled app is forbidden in store bound applications anyway right? – Woodstock Sep 26 '13 at 07:42
  • From his description, it seems like his app has genuine need for location. GPS data is location related. – Léo Natan Sep 26 '13 at 07:43
  • @LeoNatan Can the background fetch mode legitimately be used for other purposes than downloading (fetching) content? (E.g. to trigger a location update) Will Apple accept that? – Visionscaper Apr 01 '14 at 20:36
  • You can do whatever you like in the time allotted to your app. Just remember, the longer you take in the background or the more CPU you take, the less frequently the OS will wake your app. You need to measure your resource taking and see how much your app takes. – Léo Natan Apr 02 '14 at 05:10
  • @LeoNatan Thanks for the response! After my comment I found this answer, http://stackoverflow.com/a/21985926/889617 . It states that to use this background mode you need to fetch something, even if it is just some dummy data. I understand that you would disagree with that answer? – Visionscaper Apr 02 '14 at 09:05
  • Ok, I implemented a background fetch to force location updates. The only thing you seem to require is to call the completion handler with the appropriate UIBackgroundFetchResult when you got new location update(s) or an error. – Visionscaper Apr 02 '14 at 15:05
  • 1
    @Visionscaper Yes, "fetch" is something relative. You can perform work, and when finished, call the completion block. The OS has no means to understand what you do in between. – Léo Natan Apr 02 '14 at 16:44
  • @jeraldo There is no guarantee the operating system will call you every 15 minutes. – Léo Natan Jun 19 '14 at 05:59
  • @LeoNatan Thanks. I have tested this with a specific interval and you are right, there is no guarantee that the interval will be called. Do you happen to know any alternative for scheduling a 15 minute interval in the background to perform a task? – SleepNot Jun 19 '14 at 06:01
  • @jeraldo If you need to awake the app every 15 minutes exactly, you should use a silent push. – Léo Natan Jun 19 '14 at 06:03
  • By that you mean I should use push notification every 15 minutes so the app can fetch the notification and start the required method in the 15 minute mark in the background? – SleepNot Jun 19 '14 at 06:05
  • Yes. You can send a silent push, which will not alert the user, just awake the app silently in the background. – Léo Natan Jun 19 '14 at 06:06
  • @Leo Natan, The Apple Doc link you provided is broken. Can you please give me the title or new link of it. Thanks. – Tulon Jan 22 '15 at 11:28
  • Link works here. It's `-[UIApplication application:performFetchWithCompletionHandler:]`. – Léo Natan Jan 22 '15 at 11:29
2
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
loop = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(Update) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:loop forMode:NSRunLoopCommonModes];
bummi
  • 27,123
  • 14
  • 62
  • 101
Usman Nisar
  • 3,031
  • 33
  • 41
-1
NSTimer *currentCycleTimer;

UIBackgroundTaskIdentifier bgTask = UIBackgroundTaskInvalid;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
[currentCycleTimer invalidate];
currentCycleTimer=nil;
secondsLeft = 120;
currentCycleTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self        selector:@selector(Countdown) userInfo:nil repeats: YES];

-(void) Countdown
{
  [currentCycleTimer invalidate];
  currentCycleTimer=nil;
}
Ankit Goyal
  • 3,019
  • 1
  • 21
  • 26
-2
-(void)start {

[[NSUserDefaults standardUserDefaults ]setObject:[NSDate date] forKey:@"startTimer"];

 Nstimer*   timer2=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerFired) userInfo:nil repeats:YES];
}
-(void)timerFired
{
      @try {
    NSDate *timerStartDate = [[NSUserDefaults standardUserDefaults]objectForKey:@"startTimer"];


NSTimeInterval interval=[timerStartDate timeIntervalSinceNow];

int hour1=-interval/3600;

int rem =((int)interval)%3600 ;

int min1 = -rem/60 ;

int sec1 = -rem %60 ;

// NSLog(@"hour %i  rem %i",hour,rem);    
// NSLog(@"hour%i",hour1);
// NSLog(@"min%i",min1);
// NSLog(@"sec%i",sec1);


NSString *strmin=[NSString stringWithFormat:@"%i",min1];
NSString *strhour=[NSString stringWithFormat:@"%i",hour1];

if ([strmin integerValue]<10)
{
    [lblSeconds setText:[NSString stringWithFormat:@"0%@",strmin]];
}
else 
{
    lblSeconds.text=strmin;

}
if ([strhour integerValue]<10) {
    [lblHour setText:[NSString stringWithFormat:@"0%@",strhour]];
}
else
{
    lblHour.text=strhour;

}

}
@catch (NSException *exception) {
    NSLog(@"exception in timer %@ ",[exception description]);

}
  return;   
}
bummi
  • 27,123
  • 14
  • 62
  • 101
Akshay
  • 425
  • 1
  • 5
  • 16
  • -1: Just a lump of code with no explanation whatsoever. And also does not solve the problem of the question. – DarkDust Jun 23 '14 at 15:22