简体   繁体   中英

how to keep running NSTimer when app goes in background

I am creating puzzle game application and in that I am displaying time (ie 01:20) using NSTimer. NSTimer is paused when application gone in background but i want to continue it even application is in background state.

for example timer count is 15 sec when app gone in background and I put it for 5 sec and become in foreground now I need to timer count changes to 20 sec

I have searched a lot but didn't get good answer. So Please suggest me how can I achieve this.

Don't think of a timer as an object for timing something. Think of it rather as an object that pulses at a given frequency. To measure time, record a start time and compare it to the current time.

To record the start time, write it to a file as follows, probably in appWillResignActive:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *filename = [path stringByAppendingPathComponent:@"saveme.dat"];

NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self.startDate];
[data writeToFile:filename atomically:NO];
// invalidate timer

When appWillBecomeActive:

NSData *data = [NSData dataWithContentsOfFile:filename];    // using the same code as before
self.startDate = [NSKeyedUnarchiver unarchiveObjectWithData:data];
// start a timer for the purpose of pulsing only

Elapsed time at this point is:

NSDate *now = [NSDate date];
NSTimeInterval = [now timeIntervalSinceDate:self.startDate];

All of the foregoing can be done without running in the background. If you really need a timer to fire in the background, see this apple ref . Under "Background Execution". In a nutshell, you can do it, but Apple will make you meet several criteria before approving the app -- like it must be finite and provide utility for the user.

You're going to need to write that information out to a file or cache the time at exit. Then when the application resumes you read that value in, do some math, and restart your timer.

In your AppDelegate as the app is going to background save the time to a file or NSUserDefaults. You can call NSDate's class method to get an Integer value you can easily store.

+ (NSTimeInterval)timeIntervalSinceReferenceDate

At application resume, read in the value. Get the current timeIntervalSinceReferenceDate and subtract. You should have the number of seconds that have elapsed.

Create a NSDate ivar in your class to manage the starting time.

@implementation SomeClass {
  NSDate *startTime;
}

For your timer, simply calculate the time through math on this date. Your timer is more used to invoke the method that does this calculation rather than determine the time itself...

[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(updateTimer) userInfo:nil repeats:YES];

Logic for your method...

- (void)updateTimer {
  if (!startTime) {
    startTime = [NSDate date];
  }
  NSInteger secondsSinceStart = -(NSInteger)[startTime timeIntervalSinceNow];
  NSLog(@"%d", secondsSinceStart);
}

I would recommend saving the start time as an NSDate object, and then having an NSTimer that, every second while the app is running, updates the displayed time by calculating the time interval between the current time and the start time. Pause the timer when your app goes into the background (so that you don't get a lot of unnecessary fires when your app starts back up) and restart it whenever the app enters the foreground.

If you want the data to be preserved across the app shutting completely (by being left in the background for too long, or closed in the app switcher) then you'll need to save data to disk at appropriate times.

self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5f
                                 target:self
                               selector:@selector(showTime)
                               userInfo:NULL
                                repeats:YES];

- (void)showTime
{
NSDate *now=[NSDate date];
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:@"HH:mm:ss"];
timeLabel.text=[dateFormatter stringFromDate:now];
}

Hope this answer will help you....

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM