Iphone app style count down improvement? - iphone

I've been searching internet for a few days till now. I did find some useful information but just want to make things perfect.
I'm trying to write a countdown app which only uses second, my current code is a bit too complex and maybe off the main road. Looking for someone who can straight it up.
- (void)updateTimer{
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"s"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString=[dateFormatter stringFromDate:timerDate];
// where the part change time string back to int
NSString *changeToInt = timeString;
int stringInt = [changeToInt integerValue];
// loop for count down numbers
if ((buttValue - stringInt) > 0) {
leftTime = buttValue - stringInt;
[self updateValue];
} else {
leftTime = 0;
[self updateValue];
}
}
2 problems with the code, 1) do I have to go through all the date formatting to get a integer? 2) in the loop I used two variables, I was hoping to take one out and use something like --

I don't understand what you need exactly, but I think that you just want to get the number of seconds from now to a known date. The timeIntervalSinceNow method will give you a NSInteger value that represent the number of seconds from the receiver date until now, which, if the receiver is earlier than now, will be a negative value (otherwise it will be positive).
So, just to be more explicit:
- (void)updateTimer
{
leftTime = MAX(0, -[startDate timeIntervalSinceNow]); //if less than 0 will be forced to 0 -> date reached
[self updateValue];
}
As I said, I'm not sure this is what you want. If it's not, I am sorry.
Good luck!

-(void)initialiseTimer
{
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timeElapsed) userInfo:nil repeats:YES];
startDate = [[NSDate date] retain];
}
-(void)timeElapsed
{
NSLog(#"Seconds elapsed since start date %d", abs([startDate timeIntervalSinceNow]));
}
you can manipulate it to make a count down style app.

Use this code !!
-(IBAction)startAndStop:(id)sender
{
startDate = [[NSDate date]retain];
if([btnStopWatch.titleLabel.text isEqualToString:#"Start"])
{
stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/100.0 target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
[btnStopWatch setTitle:#"Stop" forState:UIControlStateNormal];
}
else if([btnStopWatch.titleLabel.text isEqualToString:#"Stop"])
{
[stopWatchTimer invalidate];
[btnStopWatch setTitle:#"Start" forState:UIControlStateNormal];
}
}
- (void)updateTimer
{
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
timeString=[dateFormatter stringFromDate:timerDate];
stopWatchLabel.text = timeString;
NSLog(#"Seconds elapsed since start date %d", abs([startDate timeIntervalSinceNow]));
}

Related

NSDate countdown with NSInterval

Here's my code:
NSDate *currDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"HH:mm:ss"];
NSString *currentTime = [dateFormatter stringFromDate:currDate];
NSDate *now = [NSDate date];
int interval = 1*60; // one minute (minutes*60)
long int nowSeconds = (long int) [now timeIntervalSince1970];
int secondsLeft = interval - (nowSeconds % interval);
NSDate *nextIntervalDate = [NSDate dateWithTimeIntervalSince1970:nowSeconds+secondsLeft];
NSString *nextTrigger = [dateFormatter stringFromDate:nextIntervalDate];
timeRemaining.text = [NSString stringWithFormat:#"%02d:%02d", secondsLeft/60, secondsLeft%60];
NSLog([NSString stringWithFormat:#"%#:%#", currentTime, nextTrigger]);
if ([currentTime isEqualToString:nextTrigger]) {
}
Problem is, 'if ([currentTime isEqualToString:nextTrigger])' is never equal. Because nextTrigger changes to the next time segment before they're equal. Here is the NSLog:
2013-01-17 15:54:59.987 app[35987:c07] 15:54:59:15:55:00
2013-01-17 15:54:59.997 app[35987:c07] 15:54:59:15:55:00
2013-01-17 15:55:00.007 app[35987:c07] 15:55:00:15:56:00 <----RIGHT HERE
2013-01-17 15:55:00.016 app[35987:c07] 15:55:00:15:56:00
My code's nextTrigger is basically a round up of the current time by the nearest minute. ALSO, this whole code segment is in a repeating NSTimer every .1 seconds.
How can I fix this?
If you have code that you'd like triggered when the next whole minute passes, it's inefficient to repeatedly check to see if said time has passed. Put that code in its own method, and create a single NSTimer to trigger it at the appropriate time.
NSDate* date = [NSDate date] ;
NSCalendar* calendar = [NSCalendar currentCalendar] ;
NSDateComponents* secondsComponents = [calendar components:NSSecondCalendarUnit fromDate:date] ;
NSTimeInterval secondsUntilNextWholeMinute = 60 - secondsComponents.second ;
[NSTimer scheduledTimerWithTimeInterval:secondsUntilNextWholeMinute target:self selector:#selector(yourMethod) userInfo:nil repeats:NO ] ;
I had a somewhat similar problem. What I did was make a copy and check it by that.(one thing is to have both oldTrigger and newTrigger declared already)Check this code
NSDate *currDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"HH:mm:ss"];
NSString *currentTime = [dateFormatter stringFromDate:currDate];
NSDate *now = [NSDate date];
int interval = 1*60; // one minute (minutes*60)
long int nowSeconds = (long int) [now timeIntervalSince1970];
int secondsLeft = interval - (nowSeconds % interval);
NSDate *nextIntervalDate = [NSDate dateWithTimeIntervalSince1970:nowSeconds+secondsLeft];
oldTrigger = nextTrigger;
nextTrigger = [dateFormatter stringFromDate:nextIntervalDate];
timeRemaining.text = [NSString stringWithFormat:#"%02d:%02d", secondsLeft/60, secondsLeft%60];
NSLog([NSString stringWithFormat:#"%#:%#", currentTime, nextTrigger]);
if ([currentTime isEqualToString:oldTrigger]) {
}

Count down timer - iPhone [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I want to display count down timer. I have the start date and end date. I need to display the remaining time like
days : hours : minutes : seconds
How can I do this?
you can set coundown like my below code :-
-(void) viewWillAppear:(BOOL)animated
{
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(updateCountdown) userInfo:nil repeats: YES];
}
AND
-(void) updateCountdown
{
NSString *dateString = #"14-12-2012";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
NSDate *dateFromString = [[NSDate alloc] init];
// voila!
dateFromString = [dateFormatter dateFromString:dateString];
NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *componentsHours = [calendar components:NSHourCalendarUnit fromDate:now];
NSDateComponents *componentMint = [calendar components:NSMinuteCalendarUnit fromDate:now];
NSDateComponents *componentSec = [calendar components:NSSecondCalendarUnit fromDate:now];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsDaysDiff = [gregorianCalendar components:NSDayCalendarUnit
fromDate:now
toDate:dateFromString
options:0];
lblDaysSetting.text=[NSString stringWithFormat:#"%02d",componentsDaysDiff.day];
lblHouresSetting.text=[NSString stringWithFormat:#"%02d",(24-componentsHours.hour)];
lblMinitSetting.text=[NSString stringWithFormat:#"%02d",(60-componentMint.minute)];
lblSecSetting.text=[NSString stringWithFormat:#"%02d",(60-componentSec.second)];
}
now just set your logic
its code output as my project as bellow::-
this is the code for .h file:
#interface UIMyContoller : UIViewController {
NSTimer *timer;
IBOutlet UILabel *myCounterLabel;
}
#property (nonatomic, retain) UILabel *myCounterLabel;
-(void)updateCounter:(NSTimer *)theTimer;
-(void)countdownTimer;
#end
and here is the code for .m file:
#implementation UIMyController
#synthesize myCounterLabel;
int hours, minutes, seconds;
int secondsLeft;
- (void)viewDidLoad {
[super viewDidLoad];
secondsLeft = 16925;
[self countdownTimer];
}
- (void)updateCounter:(NSTimer *)theTimer {
if(secondsLeft > 0 ){
secondsLeft -- ;
hours = secondsLeft / 3600;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft %3600) % 60;
myCounterLabel.text = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
}
else{
secondsLeft = 16925;
}
}
-(void)countdownTimer{
secondsLeft = hours = minutes = seconds = 0;
if([timer isValid])
{
[timer release];
}
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
[pool release];
}
hope this helps. happy coding
adrian
I would recommend the below method of getting time components of From Date to To Date.
This method is more elegant than manually decrementing 3 integer variables for hour, minute and seconds because doing so would mean you have to manually check when a second hit 0, you need to manually reset the minute back to 59 and so on. I went down this route once, it wasn't very good.
Also, when you minimize your app, the count down clock will stop. If you were decrementing your count down timer manually using 3 integers (hour, minute and seconds), minimizing your app will cause the count down to screw up.
Since this method auto calculates the difference between two dates, even when the app returns from the background minimized state, it automatically recalculates the remaining time for you without any extra code.
-(void)viewDidLoad
{
// instantiate a calendar object.
gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
countDownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateClock:) userInfo:nil repeats:YES];
[countDownTimer fire];
}
-(void)updateClock:(NSTimer *)timer
{
countDownDateFormatter = [[NSDateFormatter alloc] init];
[countDownDateFormatter setDateFormat:#"hh:mm:ss"];
NSDate *now = [NSDate date];
NSDateComponents *comp = [gregorianCalendar components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit
fromDate:now
toDate:countDownEndDate
options:0];
NSString *strTimeRemaining = nil;
// if date have not expired
if([now compare:countDownEndDate] == NSOrderedAscending)
{
strTimeRemaining = [[NSString alloc] initWithFormat:#"%02d:%02d:%02d", [comp hour], [comp minute], [comp second]];
}
else
{
// time has expired, set time to 00:00 and set boolean flag to no
strTimeRemaining = [[NSString alloc] initWithString:#"00:00:00"];
[countDownTimer invalidate];
countDownTimer = nil;
}
lblCountDown.text = strTimeRemaining;
[countDownDateFormatter release];
[strTimeRemaining release];
}

Countdown timer between time interval iPhone

I need the iPhone to recognize the current time (which I can do fine with NSDate) and have it countdown to the next time interval, say every half hour on the half hour. Example: if the current time is 2:12:30 and the interval is every half hour, I want a countdown to start at 17:30 (17 min 30 seconds left) and go to 0.
Code welcome, but also general program design thoughts welcome too. Here's the code I have for starting a countdown and getting the current time:
-(void)updateCounter:(NSTimer *)theTimer {
if(secondsLeft > 0 ){
secondsLeft -- ;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft % 3600) % 60;
waitingTimeLabel.text = [NSString stringWithFormat:#"%02d:%02d", minutes, seconds];
}
else{
secondsLeft = 10;
}
}
-(void)countdownTimer{
//secondsLeft = minutes = seconds = 0;
if([timer isValid])
{
[timer release];
}
// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
//[pool release];
}
-(NSDate *)getCurrentTime
{
NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"mm:ss";
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
NSLog(#"The Current Time is %#",[dateFormatter stringFromDate:now]);
//[dateFormatter release];
NSString *currentTime = [NSString stringWithFormat:#"%#",[dateFormatter stringFromDate:now]];
currentTimeLabel.text = currentTime;
return now;
}
NSDate *now = [NSDate date];
int interval = 30*60; // half hour
long int nowSeconds = (long int) [now timeIntervalSince1970];
int secondsLeft = interval - (nowSeconds % interval);
NSDate *nextIntervalDate = [NSDate
dateWithTimeIntervalSince1970:nowSeconds+secondsLeft];
NSLog(#"Now is %#", now);
NSLog(#"The next interval point in time is %#", nextIntervalDate);
NSLog(#"That's another %d seconds (or %02d:%02d)",
secondsLeft, secondsLeft/60, secondsLeft%60);

Local time on the iPhone

I need to display the exact local time and the time should be running.
Please help, if possible with sample code or explanation.
Thanks.
This returns the current date with Time
[NSDate date];
Now you can use NStimer to fetch the time every one second and display it.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(displayTime) userInfo:nil repeats:NO];
//Time Interval is one second
-(void) displayTime
{
NSDate *currentDate = [NSDate date];
NSDateFormatter *timeFormatter = [[[NSDateFormatter alloc]init]autorelease];
timeFormatter.dateFormat = #"HH:mm:ss a";
NSString *dateString = [timeFormatter stringFromDate: currentDate];
yourlabel.text = dateString;
[timeFormatter release]
}

Consistent 1-Second-Long lag at 0:02 during NSTimer in "stopwatch-like" app

I have an app that uses a stopwatch-style count up from 0 in HH:mm:ss format. The code looks pretty straightforward to me, and I can't think of a more efficient way to run it.
For some reason, when I run it, there is a very noticeable and consistent (every time I run it, in the same place) lag when the timer gets to 00:00:02. It stays on 00:00:02 for a full second, and then counts on normally. Why would this happen?
-(IBAction)startAndStop;
{
if (!timer) {
NSLog(#"Pressing Start Button");
[startAndStopButton setTitle:#"Stop" forState:0];
startDate = [[NSDate date] retain];
timerLabel.text = #"00:00:00";
timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(timerStart)
userInfo:nil
repeats:YES];
} else {
NSLog(#"Pressing Stop Button");
[startAndStopButton setTitle:#"Start" forState:0];
[startDate release];
[timer invalidate];
timer = nil;
[timer release];
}
}
-(void)timerStart
{
NSDate *currentDate = [NSDate date];
NSTimeInterval countInSeconds = [currentDate timeIntervalSinceDate:startDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSinceReferenceDate:countInSeconds];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"HH:mm:ss"];
[df setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString = [df stringFromDate:timerDate];
[df release];
timerLabel.text = timeString;
}
NSTimer does not fire at exact times or time intervals (check the specification for the likely error). Thus it is possible for one late firing and one early firing to occur during the same clock second, when rounded to the nearest second, and you will see a stutter effect.
Instead, use a much faster timer (or CADisplaylink), say at 30 Hz, check the time, and update the label only if the time has changed enough to change the label (one second).
The interval you are passing is in seconds:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/Reference/NSTimer.html
My guess is that it is getting called immediately, and then every 1 second afterwards, since you are passing 1 second as the timer interval. Try passing something like 1.0/20.0 to update at a higher frame rate.