iPhone: NSTimer Countdown (Display Minutes:Seconds) - iphone

I have my timer code set up, and it's all kosher, but I want my label to display "Minutes : seconds" instead of just seconds.
-(void)countDown{
time -= 1;
theTimer.text = [NSString stringWithFormat:#"%i", time];
if(time == 0)
{
[countDownTimer invalidate];
}
}
I've already set "time" to 600, or 10 minutes. However, I want the display to show 10:59, 10:58, etc. until it reaches zero.
How do I do this?
Thanks!

int seconds = time % 60;
int minutes = (time - seconds) / 60;
theTimer.text = [NSString stringWithFormat:#"%d:%.2d", minutes, seconds];

By the time, I was made a little upgrade of first answer, it removed conflicts that associated from NSInteger and int:
NSInteger secondsLeft = 987;
int second = (int)secondsLeft % 60;
int minutes = ((int)secondsLeft - second) / 60;
theTimer.text = [NSString stringWithFormat:#"%02d:%02d", minutes, second]];

Related

Very Interesting Variances with Time on Different Devices

This timmer works great on all my devices (5, Ipad and two 4S) but it doesn't seem to work on the two 3GS I have. For some reason the time runs really slow on the 3s.
Heres a video explaining the problem:
http://youtu.be/4vdusgnIXcs
And heres the code that deals with the time:
- (void)showTime
{
int hours = 0;
int minutes = 0;
int seconds = 0;
int hundredths = 0;
NSArray *timeArray = [NSArray arrayWithObjects:self.hun.text, self.sec.text, self.min.text, self.hr.text, nil];
for (int i = [timeArray count] - 1; i >= 0; i--) {
int timeComponent = [[timeArray objectAtIndex:i] intValue];
switch (i) {
case 3:
hours = timeComponent;
break;
case 2:
minutes = timeComponent;
break;
case 1:
seconds = timeComponent;
break;
case 0:
hundredths = timeComponent;
hundredths++;
score++;
break;
default:
break;
}
}
if (hundredths == 100) {
seconds++;
hundredths = 0;
}
else if (seconds == 60) {
minutes++;
seconds = 0;
}
else if (minutes == 60) {
hours++;
minutes = 0;
}
self.hr.text = [NSString stringWithFormat:#"%.0d", hours];
self.min.text = [NSString stringWithFormat:#"%.2d", minutes];
self.sec.text = [NSString stringWithFormat:#"%.2d", seconds];
self.hun.text = [NSString stringWithFormat:#"%.2d", hundredths];
scoreLabel.text= [NSString stringWithFormat:#"%i",score];
Please help me try to figure out whats going on here. It works so well on the newer devices I'm just lost at what I need to do.
Thank you in advance!
If I understand your code correctly you run a NSTimer 100 times a second.
If that is correct you may primarily have a design problem and not a performance or NSTimer problem.
A NSTimer is not guaranteed to run on time. The only thing that is guaranteed is that it will not run earlier that it is supposed to be.
Since you don't know when a timer method runs you can't rely that it will run exactly 100 times a second. This means a timer is a bad way to "count" time. A better way would be to save the system time when you start the timer, and when you want to know how much time has elapsed you use the current system time and substract the start time. The NSTimer should be used for display purposes only.
Something like this:
// instance variables:
NSDate *startDate;
NSTimer *timer;
- (void)startTimer {
[timer invalidate];
startDate = [NSDate date]; // save current time
timer = [NSTimer timerWithTimeInterval:0.075 target:self selector:#selector(displayTime:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
- (void)displayTime:(NSTimer *)timer {
// the timer method is for display only. it doesn't "count" time
// calculate elapsed time from start time
NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSinceDate:startDate];
NSInteger ti = (NSInteger)elapsedTime;
// convert elapsed time (in seconds) into hours, minutes, seconds ...
double fractionalSeconds = fmod(elapsedTime, 1);
NSInteger hundreds = fractionalSeconds * 100;
NSInteger seconds = ti % 60;
NSInteger minutes = (ti / 60) % 60;
NSInteger hours = (ti / 3600);
NSLog(#"%02d:%02d:%02d.%02d", hours, minutes, seconds, hundreds);
}
Profile your programs with Instruments.app using both devices and compare. Since you have isolated the problem in the demo, the reports it generates should quickly expose the execution time differences. Once you understand the biggest problem area(s), you will know which parts of the program you can change in order to make it run faster. Then compare your updates with the initial runs to see how the speed has improved. Repeat as needed.

countdown UILabel not get decremented

I am trying to make a count down label,
But it is not getting decremented..Can any one spot out the error in code
- (IBAction)start:(id)sender
{
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(updateCountdown) userInfo:nil repeats: YES];
}
-(void) updateCountdown
{
int hours, minutes, seconds;
int secondsLeft = 30;
hours = secondsLeft / 3600;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft %3600) % 60;
countDownlabel.text = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
}
Because each time when timer fires you use same value for seconds
int secondsLeft=30;
You must set value for secondsLeft on starting Timer and decrement it on timer
- (IBAction)start:(id)sender{
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(updateCountdown) userInfo:nil repeats: YES];
secondsLeft=30;
}
-(void) updateCountdown {
int hours, minutes, seconds;
secondsLeft--;
hours = secondsLeft / 3600;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft %3600) % 60;
countDownlabel.text = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
You can declare secondsLeft and timer as ivars, decrement secondsLeft every time updateCountdown is called and invalidate the timer when there are no seconds left to decrement.
- (IBAction)start:(id)sender
{
secondsLeft = 30;
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(updateCountdown) userInfo:nil repeats: YES];
}
- (void) updateCountdown
{
int hours, minutes, seconds;
hours = secondsLeft / 3600;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft %3600) % 60;
countDownlabel.text = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
secondsLeft--;
if (seconds==0)
{
[timer invalidate];
}
}
You have assigned int secondsLeft=30; in your updateCountdown method that's normal.
You should set the initial value of secondLeft somewhere else and then in your method updateCountdown you need to decrement it's value
-(void) updateCountdown {
int hours, minutes, seconds;
hours = secondsLeft / 3600;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft %3600) % 60;
countDownlabel.text = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
if (secondsLeft > 0) secondsLeft--;
}
I found the problem...
-(IBAction)start:(id)sender{
countDownView.hidden=NO;
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateElapsedTime) userInfo:nil repeats:YES];
secondsLeft=30;
}
-(void) updateCountdown {
int hours, minutes, seconds;
hours = secondsLeft / 3600;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft %3600) % 60;
countDownlabel.text = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
}

Display timer that works out Days, hours, minutes and seconds from a date then increments in real time

I am trying to Display a timer that works out Days, hours, minutes and seconds from a date then increments in real time on a view/page.
What would be the best approach?
you can do like this way:-
- (void)viewWillAppear:(BOOL)animated
{
[self start];
[super viewWillAppear:YES];
}
int currentTime;
- (IBAction)start{
currentTime = 0;
lbl=[[UILabel alloc]init];
//creates and fires timer every second
myTimer = [[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(showTime) userInfo:nil repeats:YES]retain];
}
- (IBAction)stop{
[myTimer invalidate];
myTimer = nil;
}
- (IBAction)reset{
[myTimer invalidate];
lbl.text = #"00:00:00";
}
-(void)showTime{
currentTime++; //= [lbl.text intValue];
//int new = currentTime++;
int secs = currentTime % 60;
int mins = (currentTime / 60) % 60;
int hour = (currentTime / 3600);
int day = currentTime / (60 * 60 * 24);
lbl.text = [NSString stringWithFormat:#"%.2d:%.2d:%.2d:%.2d",day,hour, mins, secs];
NSLog(#"my lable == %#",lbl.text);
NSLog(#"my lable == %#",lbl.text);
}
The best approach is to read the Date and Time Programming Guide to learn about using the NSDate, NSCalendar, and NSDateComponents classes.

Create a count up timer with support for hours, mins seconds, split seconds iPhone sdk

Interested in creating a timer to count up for the user.
I was wondering if I'd have to keep track of all the integer variables separately or if I could use date formatter.
I'm currently using a -scheduledTimerfoo to call an -updateLabel method with seconds, but It looks a bit horrible after 100 seconds. I'd sort of like "hours:mins:seconds:split seconds" to display.
Cheers
Sam
NSDateFormatter is only for formatting dates, not intervals of time. A better way to do this would be to record when you start the timer, and every second, update the label with how much time passed since you started the timer.
- (void)startTimer {
// Initialize timer, with the start date as the userInfo
repeatTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateLabel) userInfo:[NSDate date] repeats:YES];
}
- (void)updateLabel:(NSTimer *)timer {
// Get the start date, and the time that has passed since
NSDate *startDate = (NSDate *)[timer userInfo];
NSTimeInterval timePassed = [[NSDate date] timeIntervalSinceDate:startDate];
// Convert interval in seconds to hours, minutes and seconds
int hours = timePassed / (60 * 60);
int minutes = ((int)timePassed % (60 * 60)) / 60;
int seconds = (((int)timePassed % (60 * 60)) % 60);
NSString *time = [NSString stringWithFormat:#"%i:%i:%i", hours, minutes, seconds];
// Update the label with time string
}

iPhone : Countdown problems (00:00:00 format)

I use a UISlider to get the input in minutes (range 1 - 120) for a countdown timer and show it on a label like this "01:30:00".
i) I would like when the user sets the timer (using the slider) to adjust the hours and minutes but NOT the seconds. The seconds should start counting AFTER the user starts the countdown. How can i do that?
ii) i have trouble updating the countdownlabel. Could somebody suggest the correct code?
-(IBAction)setTime:(id)sender {
totaltime=timeSlider.value;
hours = totaltime / 60;
minutes = (totaltime % 3600) % 60;
seconds = (totaltime % 3600) * 60;
[countDownLabel setFont:[UIFont fontWithName:#"DBLCDTempBlack" size:45]];
countDownLabel.text = [NSString stringWithFormat:#"%.2i:%.2i:%.2i", hours, minutes, seconds]; }
-(void)countdown {
totaltime -=1;
if(minutes == 0) { [timer invalidate]; }
[countDownLabel setFont:[UIFont fontWithName:#"DBLCDTempBlack" size:45]];
countDownLabel.text = [NSString stringWithFormat:#"%.2i:%.2i:%.2i", hours, minutes, seconds]; }
-(IBAction)fade {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self selector:#selector (countdown) userInfo:nil repeats:YES]; }
-(IBAction)setTime:(id)sender {
totaltime=timeSlider.value;
hours = totaltime / 60;
minutes = (totaltime % 3600) % 60;
seconds = (totaltime % 3600) * 60;
[countDownLabel setFont:[UIFont fontWithName:#"DBLCDTempBlack" size:45]];
countDownLabel.text = [NSString stringWithFormat:#"%.2i:%.2i:%.2i", hours, minutes, seconds]; }
-(void)countdown {
totaltime -=1;
totaltime=timeSlider.value;
hours = totaltime / 60;
minutes = (totaltime % 3600) % 60;
seconds = (totaltime % 3600) * 60;
countDownLabel.text = [NSString stringWithFormat:#"%.2i:%.2i:%.2i", hours, minutes, seconds];
if(minutes == 0) { [timer invalidate]; }
[countDownLabel setFont:[UIFont fontWithName:#"DBLCDTempBlack" size:45]];
countDownLabel.text = [NSString stringWithFormat:#"%.2i:%.2i:%.2i", hours, minutes, seconds]; }
-(IBAction)fade {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self selector:#selector (countdown) userInfo:nil repeats:YES]; }
You're decrementing totalTime but not re-calculating your hours, minutes and seconds. So I imagine when you start the countdown, nothing ever changes? You need to recalculate the hours, minutes and seconds within your countdown method.