NSTimer - Stopwatch - iphone

I've trying to create a stopwatch with HH:MM:SS, code is as follows:
-(IBAction)startTimerButton;
{
myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
}
-(IBAction)stopTimerButton;
{
[myTimer invalidate];
myTimer = nil;
}
-(void)showActivity;
{
int currentTime = [time.text intValue];
int newTime = currentTime + 1;
time.text = [NSString stringWithFormat:#"%.2i:%.2i:%.2i", newTime];
}
Although the output does increment by 1 second as expected the format of the output is XX:YY:ZZZZZZZZ , where XX are the seconds.
Anyone any thoughts ??

Your stringWithFormat asks for 3 integers but you're only passing in one ;)
Here is some code that I've used before to do what I think you're trying to do :
- (void)populateLabel:(UILabel *)label withTimeInterval:(NSTimeInterval)timeInterval {
uint seconds = fabs(timeInterval);
uint minutes = seconds / 60;
uint hours = minutes / 60;
seconds -= minutes * 60;
minutes -= hours * 60;
[label setText:[NSString stringWithFormat:#"%#%02uh:%02um:%02us", (timeInterval<0?#"-":#""), hours, minutes, seconds]];
}
to use it with a timer, do this :
...
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateTimer:) userInfo:nil repeats:YES];
...
- (void)updateTimer:(NSTimer *)timer {
currentTime += 1;
[self populateLabel:myLabel withTimeInterval:time;
}
where currentTime is a NSTimeInterval that you want to count up by one every second.

Related

What is wrong with my countdown timer method?

Trying to make a countdown timer from a given NSTimeInterval, the label doesn't seem to be updating.
- (IBAction)startTimer:(id)sender{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerAction:) userInfo:nil repeats:YES];
}
- (void)timerAction:(NSTimer *)t {
if(testTask.timeInterval == 0){
if (self.timer){
[self timerExpired];
[self.timer invalidate];
self.timer = nil;
}
else {
testTask.timeInterval--;
}
}
NSUInteger seconds = (NSUInteger)round(testTask.timeInterval);
NSString *string = [NSString stringWithFormat:#"%02u:%02u:%02u",
seconds / 3600, (seconds / 60) % 60, seconds % 60];
timerLabel.text = string;
}
Issue is, you are decrementing the testTask.timeInterval inside the if(testTask.timeInterval == 0) , this condition never evaluates to true (because you set it to 10). That is why there is no change in the label.
You need to put that else case after the first if statement (Currently you placed it under second if statement).
You need to write your method like:
-(void)timerAction:(NSTimer *)t
{
if(testTask.timeInterval == 0)
{
if (self.timer)
{
[self timerExpired];
[self.timer invalidate];
self.timer = nil;
}
}
else
{
testTask.timeInterval--;
}
NSUInteger seconds = (NSUInteger)round(testTask.timeInterval);
NSString *string = [NSString stringWithFormat:#"%02u:%02u:%02u",
seconds / 3600, (seconds / 60) % 60, seconds % 60];
timerLabel.text = string;
}
I believe your if statements are nested incorrectly. Move your else statement to the outermost 'if' like so.
if(testTask.timeInterval == 0){
if (self.timer){
[self timerExpired];
[self.timer invalidate];
self.timer = nil;
}
} else {
testTask.timeInterval--;
}

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.

Implementing a Countdown Timer in Objective-c?

I am new to iOS programming. I am working on words matching game. In this game I need to implement time counter which shows minutes and seconds. I want when my game is started my timer to start with 3 minutes. Now I want to decrease this timer in reverse direction with seconds. my code just work for seconds..here is my code:
secondsLeft--;
int seconds = (secondsLeft %3600) % 60;
Timerlbl.text = [NSString stringWithFormat:#"%02d",seconds];
if (seconds==0)
{
UIAlertView *pAlert = [[UIAlertView alloc]initWithTitle:#"Sorry!!"
message:#"TimeOver" delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:#"Cancel",nil];
[pAlert show];
[pAlert release];
}
}
In Viewdidload i call it through timer..
countDown=[NSTimer scheduledTimerWithTimeInterval:5.0 target:self
selector:#selector(TimeOver) userInfo:nil repeats:YES];
pleas any one guide me how can i do it in both minutes and seconds.
You can do it like this(ARC Enabled):-
#interface ViewController()
{
UILabel *progress;
NSTimer *timer;
int currMinute;
int currSeconds;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
progress=[[UILabel alloc] initWithFrame:CGRectMake(80, 15, 100, 50)];
progress.textColor=[UIColor redColor];
[progress setText:#"Time : 3:00"];
progress.backgroundColor=[UIColor clearColor];
[self.view addSubview:progress];
currMinute=3;
currSeconds=00;
// Do any additional setup after loading the view, typically from a nib.
}
-(void)start
{
timer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerFired) userInfo:nil repeats:YES];
}
-(void)timerFired
{
if((currMinute>0 || currSeconds>=0) && currMinute>=0)
{
if(currSeconds==0)
{
currMinute-=1;
currSeconds=59;
}
else if(currSeconds>0)
{
currSeconds-=1;
}
if(currMinute>-1)
[progress setText:[NSString stringWithFormat:#"%#%d%#%02d",#"Time : ",currMinute,#":",currSeconds]];
}
else
{
[timer invalidate];
}
}
I know this is old question, but I want to share my way to achieve this. We have method (timeIntervalSinceDate:) to calculate the interval and have fixed amount of seconds to count down. In my case 300 s.
UPDATE JULY, 2015 SWIFT
#IBAction func startTimer(sender: UIButton) {
sender.selected = !sender.selected;
//if selected fire timer, otherwise stop
if (sender.selected) {
self.timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateTimer"), userInfo: nil, repeats: true);
self.startDate = NSDate();
} else {
self.stopTimer();
}
}
func stopTimer() {
self.timer.invalidate();
}
func updateTimer() {
// Create date from the elapsed time
var currentDate:NSDate = NSDate();
var timeInterval:NSTimeInterval = currentDate.timeIntervalSinceDate(self.startDate!);
//300 seconds count down
var timeIntervalCountDown = 300 - timeInterval;
var timerDate:NSDate = NSDate(timeIntervalSince1970: timeIntervalCountDown);
// Create a date formatter
var dateFormatter = NSDateFormatter();
dateFormatter.dateFormat = "mm:ss";
dateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0);
// Format the elapsed time and set it to the label
var timeString = dateFormatter.stringFromDate(timerDate);
self.timerLabel?.text = timeString;
}
Working github swift sample project
Objective-C
- (void)updateTimer
{
// Create date from the elapsed time
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate
timeIntervalSinceDate:self.startDate];
NSLog(#"time interval %f",timeInterval);
//300 seconds count down
NSTimeInterval timeIntervalCountDown = 300 - timeInterval;
NSDate *timerDate = [NSDate
dateWithTimeIntervalSince1970:timeIntervalCountDown];
// Create a date formatter
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
// Format the elapsed time and set it to the label
NSString *timeString = [dateFormatter stringFromDate:timerDate];
self.stopWatch.text = timeString;
}
- (void)stopTimer
{
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
[self updateTimer];
}
- (void)startTimer
{
if (self.stopWatchTimer) {
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
}
self.startDate = [NSDate date];
// Create the stop watch timer that fires every 100 ms
self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
}
UPDATE:
it is extremely expensive to create a NSDateFormatter each time you pass through updateTimer. Far better to create the NSDateFormatter outside the loop and reuse it. Credits: #siburb
In .h file
IBOutlet UILabel* lblTimer;
NSTimer* gameTimer;
In .m file
-(void)viewDidLoad
{
[super viewDidLoad];
[self createTimer];
}
- (void)createTimer
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
gameTimer = [[NSTimer timerWithTimeInterval:1.00 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES] retain];
[[NSRunLoop currentRunLoop] addTimer:gameTimer forMode:NSDefaultRunLoopMode];
timeCount = 20;
[runLoop run];
[pool release];
}
- (void)timerFired:(NSTimer *)timer
{
if(timeCount == 0)
{
[self timerExpired];
}
else
{
timeCount--;
if(timeCount == 0) {
[timer invalidate];
[self timerExpired];
}
}
lblTimer.text = [NSString stringWithFormat:#"%02d:%02d",timeCount/60, timeCount % 60];
self.title = lblTimer.text;
}
Bind the above Label Outlet with Label in View.
It is working correctly with Me
Simple and less code in Objective-C,
in .h file create objects for Timer and totalSeconds
NSTimer *timer;
int totalSeconds;
.m file
//you can call this method where you want
[self startTimer];
-(void)startOtpTimer {
totalSeconds = 120;//your time
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
selector:#selector(updateCountDownTime) userInfo:nil repeats:YES];
}
-(void)updateCountDownTime {
[self populateLabelwithTime:totalSeconds];
if( totalSeconds != 0) {
totalSeconds -= 1;
} else {
[timer invalidate];//stop timer
self.timeLabel.text = #"";//after reach 0 you can set empty string
}
}
- (void)populateLabelwithTime:(int)seconds {
self.timeLabel.text = [NSString stringWithFormat:#"%02d", totalSeconds];
}
You can use NSTimer to achieve this.

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.