how to keep running NSTimer when app goes in background - iphone

I am creating puzzle game application and in that I am displaying time (i.e 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.

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);
}

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.

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....

Related

Adding Timer to iPhone

I am trying add a feature where On certain push, my timer will be started and even the app is close the timer will continue. Lets say my Points were 10 and now timer started. Once i close the app, maybe next time if i open the app the
1- If before 20 min it will show a count down timer running
2- if after 20 min at app again start it will add point to 10.
Now what Kind of timer or class can help me do this?
Regards
NSTimer will not continue more than 600 seconds even if your app is in background, rest terminating the app.
you can rather do this:
NSString *prevTimestamp = [NSString stringWithFormat:#"%d",
[[NSDate date] timeIntervalSince1970]];
store this prevTimestamp in NSUserDefaults, and when coming back to the app,
NSString *nowTimestamp = [NSString stringWithFormat:#"%d",
[[NSDate date] timeIntervalSince1970]];
time difference will be [nowTimestamp floatValue] - [prevTimestamp floatValue]
In your delegate for app terminiation save the time in NSUserdefaults and while you laucnch the app read it back and go on to add the time on that.
Within your applicationdelegate, you have these functions:
-(void)applicationDidEnterBackground:(UIApplication *)application;
and
-(void)applicationWillEnterForeground:(UIApplication *)application;
From these functions you can track time through something like this:
-(void)applicationDidEnterBackground:(UIApplication *)application
{
backgroundTime = [[NSDate date] timeIntervalSince1970];
}
-(void)applicationWillEnterForeground:(UIApplication *)application
{
double timetoAppend = [[NSDate Date] timeIntervalSince1970] - backgroundTime];
// from here you need to add the timetoAppend to your own variable
}

Get the time to "run" in iOS

I've read a guide about how to make a clock, in iOS. And that works like it should and all that, but i want to go further and get the clock to update each minut. So it's no longer "static", so if you open the application 12:16 am, and let it run it should automatically update each minut(12:17 am, 12:18am etc.).
This is the code the guide provided me with,
NSDateFormatter *datoVar = [[NSDateFormatter alloc] init];
[datoVar setDateFormat:#"hh:mm"];
LabelKlokken.text = [datoVar stringFromDate:[NSDate date]];
I've tried and tried to look through google and stackoverflow, but just can't find anything.
Thanks in advance, Oluf Nielsen.
EDITED : My code now looks like this
-(void)clock
{
NSDateFormatter *datoVar = [[NSDateFormatter alloc] init];
[datoVar setDateFormat:#"hh:mm"];
LabelKlokken.text = [datoVar stringFromDate:[NSDate date]];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self clock];
tid = nil;
tid = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(clock) userInfo:NULL repeats:YES];
}
You can schedule an NSTimer to check for time every 60 seconds.
dateTimer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(updateTime) userInfo:nil repeats:YES];
put your code in updateTime method. Better yet, check it every second, because it could happen that you switch time in 59th second of each minute thus being 59 seconds behind...
Remember to invalidate the timer once you want to quit updating so your app doesn't crash when you switch views or something.
[dateTimer invalidate];
dateTimer = nil;

UILocalNotification : updating BadgeNumber during repeatInterval

After goggling for 2 days i couldn't find any solution as if its clear to everyone (but me) !
I need the:
Alert.applicationIconBadgeNumber = x
to be updated in background each time the notification fires, I am repeating the notify by:
notif.repeatInterval = NSMinuteCalendarUnit
Repeating is working fine every 1 m. when the app goes in background, but the BadgeNumber dosent get updated, it takes the 1st updated date value only.
I am calling the scheduleNotification method by viewDidLoad
Here is my full code:
- (void)scheduleNotification {
UILocalNotification *notif;
notif = [[[UILocalNotification alloc] init] autorelease];
notif.timeZone = [NSTimeZone defaultTimeZone];
notif.fireDate = [[NSDate date] dateByAddingTimeInterval:5];
notif.repeatInterval = NSMinuteCalendarUnit;
NSInteger BadgeNumber = [self BadgeNumber];
NSInteger *BadgeNumberPointer = &BadgeNumber;
NSString *BadgeNumberString = [NSString stringWithFormat:#"%i", BadgeNumber];
notif.applicationIconBadgeNumber = *BadgeNumberPointer;
notif.alertBody = BadgeNumberString;
notif.alertAction = #"Hello";
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
}
-(int)BadgeNumber{
NSDate *currentDateUpdate = [[NSDate alloc] init];
NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
[formatter2 setDateFormat:#"dd"];
NSString *dateCheckUpdate = [formatter2 stringFromDate:currentDateUpdate];
NSInteger dateCheckUpdateInt = [[dateCheckUpdate substringWithRange:NSMakeRange(0, 2)] integerValue];
int BadgeNumber = dateCheckUpdateInt;
return BadgeNumber;
}
Kindly advice how to fix it,, thanking all of you.
Because the operating system copies the notification when scheduled, the data in the notification is not updated, therefore the application badge number doesn't change.
Maybe if you don't repeat the notification but generate your own new notification for each time interval it will give you the behavior you need. The only way I can think of generating notifications like that is to post a bunch of notifications in your scheduleNotification method, and then remember to delete the notifications when the user responds in the proper way. Since the OS only remembers the next chronologically scheduled 64 notifications, you could only schedule about an hour's worth. Since your badge number seems to be the current date, you could check the time and only bother with setting so many notifications if you're within an hour of midnight.
I don't understand what you are trying to accomplish by nagging the user so often, nor telling them the date in the badge number. Any app that bothered me so much or misused the badge number so would quickly get deleted from my iOS devices. Maybe rethinking what you are trying to accomplish may direct you to a better solution.
I know this is already answered, but you could use NSUserDefaults as a means of caching the badge count. Then in applicationIconBadgeNumber you can just use something like this:
notif.applicationIconBadgeNumber = ([NSUserDefaults standardUserDefaults] integerForKey:#"badgeCount"] + 1);
and then you could just reset it when the user responds accordingly.

calculating total time of downloading data?

i am using apple's sample URLCache,but when i mention url, it loads data perfectly
but i want to calculate time of downloading(till completion),is there anyh built in method?
Add NSDate property to your class, name it,let's say, downloadStart and when download starts, save actual time to it - self.downloadStart = [NSDate date];
Then in -connectionDidFinishLoading: delegate method implementation do:
NSDate *downloadEnd = [NSDate date];
NSTimeInterval totalTime = ([downloadEnd timeIntervalSince1970] - [downloadStart timeIntervalSince1970]);
//Total time now contains number of seconds since download start time
NSLog(#"Download finished in %f seconds", totalTime);
self.downloadStart = nil;
That's it. Please note that the code above is just a kind of abstract how to do the trick, so don't use in copy & paste manner.

Get EXEC_BAD_ACCESS when I get the NSFileModificationDate

I try to get the last modification date of a file:
NSFileManager *fm = [[NSFileManager alloc] init];
NSError *err;
NSDate *lastModif = [[fm attributesOfItemAtPath:filename error:&err] objectForKey:NSFileModificationDate];//filename is ok ;-)
if(err == nil) {
[lastModif retain];
//I can put a NSLog of lastModif here, it works !!
NSTimeInterval lastModifDiff = [lastModif timeIntervalSinceNow];//crash here
}
I don't understand why the NSDate seems to be released, why the retain does not retain it.
Thank you if you have any idea...
You don't need to retain lastModif. I think you might be trying to treat lastModifDiff as an object of some sort when you do an NSLog with it or whatever you do with it afterwards. NSTimeInterval is a typedef to a double so you need to treat it as a double or [NSNumber numberWithDouble:lastModifDiff] if you want to use it like an object.
I'm having the same problem, but this post seemed germane:
NSDate : timeIntervalSinceNow crash
I'm writing a simple set of functions- startClock/endClock -using NSDate to determine FPS in my game loop. Except that timeIntervalSinceNow crashes, claiming that my earlier set NSDate object doesn't exist.
I know for a fact that the NSDate object has a retain count of 1 when I call startClock, but my theory is that NSDate instances are internally rigged to auto-release when they get bored and aren't feeling useful.
Using retain/release to assume ownership of these flighty and ephemeral NSDate objects worked for me.