Adding Timer to iPhone - 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
}

Related

how to keep running NSTimer when app goes in background

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

how do I play an alarm sound for more than 30 seconds like the alarm clock pro app?

I'm trying to build an alarm clock similar to the Alarm Clock Pro and the Nightstand application that are currently in the app store. Each of these applications is able to play an alarm clock sound for more than 30 seconds when the alarm time is hit (usually the next morning).
I've tried two approaches already with no luck:
Approach 1:
[self performSelector:#selector(playAlarm) withObject:nil afterDelay:myDouble];
Approach 2:
UILocalNotification *notif = [[cls alloc] init];
notif.fireDate =[datePicker date];//firedate;
notif.timeZone = [NSTimeZone systemTimeZone];
notif.alertBody = #"Time to wake up!";
NSString *SoundFileName=nil;
if([[[NSUserDefaults standardUserDefaults] objectForKey:#"ActualSoundFile"] isKindOfClass:[NSString class]])
SoundFileName=[[[NSString alloc]initWithString:[[NSUserDefaults standardUserDefaults]objectForKey:#"ActualSoundFile"]]autorelease];
else
SoundFileName=[[[NSString alloc] initWithString:#""] autorelease];
if([SoundFileName length]>1)
notif.soundName = [SoundFileName stringByAppendingString:#".wav"];
else
notif.soundName = UILocalNotificationDefaultSoundName;
notif.alertAction=#"Snooze";
notif.repeatCalendar=[NSCalendar currentCalendar];
notif.repeatInterval =NSDayCalendarUnit;
NSDictionary *userDict = [NSDictionary dictionaryWithObject:#"Alarm" forKey:kRemindMeNotificationDataKey];
notif.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[notif release];
Does anyone know how they're able to play the alarm on a loop after 7 hours?
The selected answer is not the right answer, because the user may wake up during the first notification and choose to close it. Guess what, the second notification comes along giving the user the impression that the alarm is broken.
The correct answer according to App docs is as follows:
You can not play a sound more than 30 seconds when your notification arrives while your app is in the background (e.g. user closes the app before going to sleep).
To play a longer sound, you must tell your user to leave the alarm app in the foreground before going to sleep, then in didReceiveLocalNotification you implement playing a longer sound manually.
You need to fire local notification by assigning date into fireDate property, and assign sound file into
UILocalNotification *localNotif = [[[UILocalNotification alloc] init]autorelease];
localNotif.fireDate = scheduleDate;
NSLog(#"fireDate is %#",localNotif.fireDate);
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = #"WAKE UP...!!!";
localNotif.alertAction = #"View";
localNotif.soundName = #"Default.wav";
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
This way, local notification will be fired even if application is closed, remember that "Default.wav" file should be less than or equal to 30 seconds, Even Alarm clock pro app plays sound =30 seconds in local notification.
If application is alive, you can implement delegate method of appdelegate, and can apply your logic to display alert view and play sound even >30 seconds .....
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
}
So I think I found a valid solution:
To simulate the alarm sound playing for more than 30 seconds, just add multiple localnotifications one after the other, 30 seconds apart.

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.

Not the NSTimer or the applicationSignificantTimeChange then what do I use?

I want text to change once a day even if my app is not open at the time NSTimer doesn't run while your app is closed, applicationSignificantTimeChange won't get the message if my app is closed either.
What I need to do is.
(1) get the current date
(2) choose a phrase based on the current date and
(3) update your label
I still might use NSTimer or applicationSignificantTimeChange to handle the case where my app is open at midnight, but I need to get the phrase-picking method working first so my timer or time change method can call it at midnight for the new date
Can anyone help me out with this problem and what I need to do to make it work?
I hope this code is good enough to stop all the similar questions you are asking way too often.
Yes, lesson for the future: bug me with a lot of questions in categories I'm interested in and I will deliver the code.
- (void)updateLabelForDate:(NSDate *)date {
NSTimeInterval timeInterval = [date timeIntervalSinceReferenceDate];
NSInteger days = timeInterval / (60*60*24);
NSArray *sloganArray = [NSArray arrayWithObjects:
NSLocalizedString(#"Slogan for day 1", nil),
NSLocalizedString(#"Slogan for day 2", nil),
NSLocalizedString(#"Slogan for day 3", nil),
NSLocalizedString(#"I'll hope you'll get it", nil),
nil];
NSInteger usedSloganIndex = (int)days % [sloganArray count];
NSString *slogan = [sloganArray objectAtIndex:usedSloganIndex];
NSLog(#"Slogan: %#", slogan);
}
- (void)applicationSignificantTimeChange:(UIApplication *)application {
[self updateLabelForDate:[NSDate date]];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
[self updateLabelForDate:[NSDate date]];
// the following is there to prove that this code works.
NSDate *date = [NSDate date];
for (int i = 0; i < 10; i++) {
NSLog(#"Date: %#", date);
[self updateLabelForDate:date];
date = [date dateByAddingTimeInterval:(60*60*24)];
}
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[self updateLabelForDate:[NSDate date]];
}
You can't, if the application isn't running.
You can however use a "Local Notification" - which is sort of like a "Push Notification" - except it is sent by your own device - to tell you that the app needs attention. This can be scheduled.
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction/Introduction.html

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.