Rectangle 27 15

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.

@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;
}
- (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];
}

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 case anybody is going to copy/paste this verbatim (you know who you are - ), 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.

@siburb, fair point, will include your comment in update

iphone - Implementing a Countdown Timer in Objective-c? - Stack Overfl...

iphone objective-c ios nstimer
Rectangle 27 0

Sticking with the code you already have, here is how advanceTimer method should look to make it work:

- (void)advanceTimer:(NSTimer *)timer
{
    [countdown setIntegerValue:([countdown integerValue] - 1)];
    if ([countdown integerValue] == 0)
    {
        // code to stop the timer
    }
}

edit: To make the whole thing more object-oriented, and to avoid converting from strings to numbers and back every time, I would instead do something like this:

// Controller.h:
@interface Controller
{
    int counter;
    IBOutlet NSTextField * countdownField;
}
@property (assign) int counter;
- (IBAction)startCountdown:(id)sender;
@end
// Controller.m:
@implementation Controller

- (IBAction)startCountdown:(id)sender
{
    counter = 60;

    NSTimer *countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1
                                         target:self
                                       selector:@selector(advanceTimer:)
                                       userInfo:nil
                                        repeats:YES];
}

- (void)advanceTimer:(NSTimer *)timer
{
    [self setCounter:(counter -1)];
    [countdownField setIntegerValue:counter];
    if (counter <= 0) { [timer invalidate]; }
}

@end

And, if you can make use of bindings, you could simply bind the text field's intValue to the counter property of the Controller. This would allow you to elminate the IBOutlet in the class interface, and the setIntegerValue: line in advanceTimer.

update: Removed the code which adds the timer to the run loop twice. Thank you to Nikolai Ruhe and nschmidt for noticing that error.

update: Used the setIntegerValue method to simplify the code, as per nschmidt.

edit: Typo in definition of (void)advanceTimer:(NSTimer *)timer ... caused annoying 'unrecognized selector sent to instance' exception

The countdownTimer is added to the run loop twice, which is wrong.

@Nikolai Ruhe: Thank you for pointing that out. I have removed the incorrect code from my examples.

I guess setIntegerValue is more efficient than [NSString stringWithFormat:], so I would not have made this "optimization". Especially since it doesn't help the clarity of the code.

@nschmidt: I'm sure you're right. I wasn't sure about the usage, and I don't have a compiler in front of me, so I just went with what I knew would work.

@nschmidt: I've changed it back to setIntegerValue. You're absolutely right about the added confusion.

objective c - Countdown Timer - Stack Overflow

objective-c cocoa
Rectangle 27 0

It seems that you are misunderstanding a few things here.

When you instantiate your timer, it goes off on its own and then calls your selector every 1.0 seconds. The original execution continues as normal, checking your condition and then exiting viewDidLoad. You never check the condition again. Here's a basic ordering of your events:

  • You create a timer.
  • You check to see if timerLabel is not 0.
updateCountDown

Your exercisePopup method is never called because you do not check your condition in updateCountDown.

Your comparison of timerLabel using isEqual: and the integer literal 0 is the same as if you had written:

if (![timerLabel isEqual:nil]) {

This is clearly not what you intended; you are trying to compare the string value associated with the timerLabel to the string value of @"0".

if (![timerLabel.text isEqualToString:@"0"]) {

However, this is not the best way to compare times. You should consider using NSTimeIntervals and comparing them. You may also want to look into scheduling your time updates with your display using CADisplayLink so that you're not waiting on a timer that is potentially out-of-sync.

objective c - IOS Stop Countdown Timer at 0 - Stack Overflow

ios objective-c timer
Rectangle 27 0

Where is rocketTimer instantiated? You seem to have left that very important detail out. My guess is that rocketTimer isn't being correctly retained by your code and that is causing your crash when trying to access that object after it has been deallocated.

I'd suggest synthesizing your property and then using the built-in setting by setting self.rocketTimer when you initialize.

@interface FirstViewController : UIViewController {
    NSTimer *rocketTimer;
}
@property (nonatomic, retain) NSTimer *rocketTimer;
- (IBAction)Start;
@end
@implementation FirstViewController
@synthesize rocketTimer;
// test of implementation
// ...

also, call [super dealloc] last in your dealloc.

"Where is rocketTimer instantiated? You seem to have left that very important detail out" No, he didn't. It's instantiated in the last line of the if-clause of his Start-method.

@danyowdee Yep, missed that line. In any case, the timer isn't retained properly.

It doesn't need to: The timer is repeating and scheduled on the runloop which retains the timer (see paragraph 2 sentence 2) until invalidate is called on it.

objective c - Countdown timer using NSTimer in "0:00" format - Stack O...

objective-c cocoa-touch nstimer countdown
Rectangle 27 0

Several things are wrong with your code:

You are passing a wrong parameter for the time interval

  • You are calling the wrong overload - you are expected to pass an invocation object, yet you are passing a NULL

You put the code that you want executed on timer together with timer initialization

You should call the overload that takes a selector, and pass 1 for the interval, rather than -1.

NSTimer *timer
int remainingCounts
timer = [NSTimer scheduledTimerWithTimeInterval:1
                                         target:self
                                       selector:@selector(countDown)
                                       userInfo:nil
                                        repeats:YES];
remainingCounts = 60;

to the place where you want to start the countdown. Then add the countDown method itself:

-(void)countDown {
    if (--remainingCounts == 0) {
        [timer invalidate];
    }
}

wouldn't it fire once more than he wants to that way? I think it should be --remainingCounts == 0 ,no?

remainingCounts = 59
--remainingCounts

Thanks for your feedback dasblinkenlight. However, still struggling to get it running! At the moment my selector is not communicating with the countDown method i.e. nothing is happening when I compile the code. Could this be because the timer has not started or that they are not linked?

@MatthewNieuwenhuys This could be necause of any of the reasons that you mention. Make sure that timer is an instance variable, that the call to scheduled timer with interval is happening (add NSLog) and that countDown is on the same class as the call that sets up the timer. Add NSLog as necessary to see what gets called.

Thanks dasblinkedlight, this may be a silly question but I need to initiate the countDownTimer from my view controller.m - so far I have put [game countDownTimer]; - what do I need to add to start the countDownTimer from my view controller?

objective c - (NSTimer) creating a Timer Countdown - Stack Overflow

objective-c xcode nstimer
Rectangle 27 0

This can be done using one time, and one label. Try using the following code:

int seconds = [countDown.text intValue] % 60; 
int minutes = ([countDown.text intValue] / 60) % 60; 
countDown.text = [NSString stringWithFormat:@"%2d:%02d", minutes, seconds];

and if i want a Tenth of a second also(milliseconds)?

@cnaaniomer see my edited answer, not 100% about this, but it should be as simple as converting the ints to floats and formatting them to show decimal places.

but now i get this error : invalid operands to binary expression float and float. what is the problem?

The % (modulo) operator only works on integers. You must be using a float somewhere.

objective c - countdown timer with minutes and seconds - Stack Overflo...

objective-c nstimer
Rectangle 27 0

Put this in -(void)viewDidLoad method

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self
                                                   selector:@selector(countDownTimer) userInfo:nil repeats:YES];

then create the -(void)countDownTimer method

- (void)countDownTimer {
    // my method which returns the differences between two dates in my case
    double diff = [self getDateDifference];

    double days     = trunc(diff / (60 * 60 * 24));
    double seconds  = fmod(diff, 60.0);
    double minutes  = fmod(trunc(diff / 60.0), 60.0);
    double hours    = fmodf(trunc(diff / 3600.0), 24);

    if(diff > 0) {
        NSString *countDownString = [NSString stringWithFormat:@"%02.0f day(s)\n%02.0f:%02.0f:%02.0f",
                           days, hours, minutes, seconds];
        // IBOutlet label, added in .h
        self.labelCountDown.text= countDownString;
    } else {
        // stoping the timer
        [timer invalidate];
        timer = nil;
        // do something after countdown ...
    }
}

and you can add a - (double)getDateDifference method which returns the difference between two dates in my case

- (double)getDateDifference {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    NSDate *dateFromString = [[NSDate alloc] init];
    NSDate *now = [NSDate date];
    NSString *myDateString = @"2013-10-10 10:10:10"; // my initial date with time
    // if you want to use only time, than delete the 
    // date in myDateString and setDateFormat:@"HH:mm:ss"

    // this line is not required, I used it, because I need GMT+2
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:+2]];

    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

    // get the date
    dateFromString = [dateFormatter dateFromString:myDateString];

    // this line is also not required, I used it because I need GMT+2
    // so I added two hours in seconds to 'now'
    now = [now dateByAddingTimeInterval:60*60*2];

    // getting the difference
    double diff = [dateFromString timeIntervalSinceDate:now];

    NSLog(@"dateString: %@", dateString);
    NSLog(@"now: %@", now);
    NSLog(@"targetDate: %@", dateFromString);
    NSLog(@"diff: %f", diff);

   return diff;
}
dateString: 2013-10-10 00:20:00
now: 2013-10-10 00:20:00 +0000
target: 2013-10-10 00:20:28 +0000
diff: 28.382786

objective c - How to add time to a countdown timer to iOS Project - St...

ios objective-c nstimer
Rectangle 27 0

- (IBAction)buttonPressed:(id)sender
{
    [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(timerExpired) userInfo:nil repeats:NO];
}

- (void)timerExpired
{
    NSLog(@"Your two seconds are up!");
}

@Dan The objective is not to call NSLog, but instead to demonstrate how to create a one-shot NSTimer as the question states. Do you have an example that you recommend instead? Share your answer.

create a countdown timer in objective c (iPhone development) - Stack O...

iphone objective-c ios timer countdowntimer
Rectangle 27 0

From the question you posed.you can achieve that by invoking a function for every 1 sec and handle the decrement logic in that.

NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 1.0
                      target: self
                      selector:@selector(onTick:)
                      userInfo: nil repeats:YES];
(void)onTick
{
   //do what ever you want
   NSLog(@"i am called for every 1 sec");
//invalidate after 60 sec [timer invalidate];
}

Do I write the onTick method within the same method as the CountdownTimer?

you can use CountdownTimer method itself instead of onTick sorry to confuse you by writting different method name.

objective c - (NSTimer) creating a Timer Countdown - Stack Overflow

objective-c xcode nstimer
Rectangle 27 0

- (IBAction)buttonPressed:(id)sender
{
    [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(timerExpired) userInfo:nil repeats:NO];
}

- (void)timerExpired
{
    NSLog(@"Your two seconds are up!");
}

@Dan The objective is not to call NSLog, but instead to demonstrate how to create a one-shot NSTimer as the question states. Do you have an example that you recommend instead? Share your answer.

create a countdown timer in objective c (iPhone development) - Stack O...

iphone objective-c ios timer countdowntimer
Rectangle 27 0

Do it exactly the same way, just add another timer.

countdownTimer2 = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(countdown2) userInfo:nil repeats:YES];

-(void)countdown2
{
    countdownCounterMinutes -= 1;
}

and change countdown to

-(void)countdown
{
    countdownCounter -= 1;
    countdown.text = [NSString stringWithFormat:@"%i%i", countdownCounterMinutes, countdownCounter];

}

objective c - countdown timer with minutes and seconds - Stack Overflo...

objective-c nstimer
Rectangle 27 0

if(![timerLabel isEqual: 0]

This line is your problem. You're comparing a UILabel with 0, which is the same as checking if this UILabel is nil, which it is not in viewDidLoad because you're loading from a nib file where this label exists. so [timerLabel isEqual:0] always equals false, which is why negating the entire if statement makes the alert fire. You need to think of an alternative way of counting 10 repetitions of the NSTimer firing.

Try keeping a count of how many times updateCountDown has fired using a static int declared in that method.

objective c - IOS Stop Countdown Timer at 0 - Stack Overflow

ios objective-c timer
Rectangle 27 0

if([[NSDate date] timeIntervalSinceDate:startDate]>=countLimit)

[myTimer invalidate];

it gives me two warnings:- 1. Class method'+timeIntervalSinceDate:' not found(return type defaults to 'id'). 2. Ordered comparison between pointer and integer('id' and 'int')

objective c - Xcode - setting limit for NSDate CountDown timer - Stack...

objective-c xcode nsdate nstimer nstimeinterval
Rectangle 27 0

Several things are wrong with your code:

You are passing a wrong parameter for the time interval

  • You are calling the wrong overload - you are expected to pass an invocation object, yet you are passing a NULL

You put the code that you want executed on timer together with timer initialization

You should call the overload that takes a selector, and pass 1 for the interval, rather than -1.

NSTimer *timer
int remainingCounts
timer = [NSTimer scheduledTimerWithTimeInterval:1
                                         target:self
                                       selector:@selector(countDown)
                                       userInfo:nil
                                        repeats:YES];
remainingCounts = 60;

to the place where you want to start the countdown. Then add the countDown method itself:

-(void)countDown {
    if (--remainingCounts == 0) {
        [timer invalidate];
    }
}

wouldn't it fire once more than he wants to that way? I think it should be --remainingCounts == 0 ,no?

remainingCounts = 59
--remainingCounts

Thanks for your feedback dasblinkenlight. However, still struggling to get it running! At the moment my selector is not communicating with the countDown method i.e. nothing is happening when I compile the code. Could this be because the timer has not started or that they are not linked?

@MatthewNieuwenhuys This could be necause of any of the reasons that you mention. Make sure that timer is an instance variable, that the call to scheduled timer with interval is happening (add NSLog) and that countDown is on the same class as the call that sets up the timer. Add NSLog as necessary to see what gets called.

Thanks dasblinkedlight, this may be a silly question but I need to initiate the countDownTimer from my view controller.m - so far I have put [game countDownTimer]; - what do I need to add to start the countDownTimer from my view controller?

objective c - (NSTimer) creating a Timer Countdown - Stack Overflow

objective-c xcode nstimer
Rectangle 27 0

- (void)startCountdown
{
    _counter = 60;

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1
                                                      target:self
                                                    selector:@selector(countdownTimer:)
                                                    userInfo:nil
                                                     repeats:YES];
}

- (void)countdownTimer:(NSTimer *)timer
{
    _counter--;
    if (_counter <= 0) { 
        [timer invalidate];
        //  Here the counter is 0 and you can take call another method to take action
        [self handleCountdownFinished];
   }
}

I made counter a property and with auto synthesized properties Xcode uses an underscore.

it keeps saying 'Use of undeclared identifier' _counter, how can I solve this?

objective c - (NSTimer) creating a Timer Countdown - Stack Overflow

objective-c xcode nstimer
Rectangle 27 0

Implement an onscreen countdown via whatever means you want and start it when you start the 5 second duration video recording. Then tear it down when the video stops recording.

objective c - camera countdown timer issue - Stack Overflow

objective-c camera
Rectangle 27 0

for anyone who what the answer in the end i do it this way:

-(IBAction)start
{
    timer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self     selector:@selector(updateTimer:) userInfo:nil repeats:YES];
}

-(void)updateTimer:(NSTimer *)timer {
    currentTime -= 10 ;
    [self populateLabelwithTime:currentTime];
    if(currentTime <=0)
       [timer invalidate];
}


- (void)populateLabelwithTime:(int)milliseconds {
    seconds = milliseconds/1000;
    minutes = seconds / 60;
    hours = minutes / 60;

    seconds -= minutes * 60;
    minutes -= hours * 60;

    NSString * result1 = [NSString stringWithFormat:@"%@%02d:%02d:%02d:%02d", (milliseconds<0?@"-":@""), hours, minutes, seconds,milliseconds%1000];
    result.text = result1;

}

in viewDidLoad i set currentTime for the countdown time in milliseconds. hope you understand...

objective c - countdown timer with minutes and seconds - Stack Overflo...

objective-c nstimer
Rectangle 27 0

Here's an example of how to implement a countdown timer in SpriteKit.

First, declare a method that creates 1) a label node to display the time left and 2) the appropriate actions to update the label, wait for one second, and rinse/lather/repeat

- (void) createTimerWithDuration:(NSInteger)seconds position:(CGPoint)position andSize:(CGFloat)size {
    // Allocate/initialize the label node
    countDown = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    countDown.position = position;
    countDown.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
    countDown.fontSize = size;
    [self addChild: countDown];
    // Initialize the countdown variable
    countDownInt = seconds;
    // Define the actions
    SKAction *updateLabel = [SKAction runBlock:^{
        countDown.text = [NSString stringWithFormat:@"Time Left: %ld", countDownInt];
        --countDownInt;
    }];
    SKAction *wait = [SKAction waitForDuration:1.0];
    // Create a combined action
    SKAction *updateLabelAndWait = [SKAction sequence:@[updateLabel, wait]];
    // Run action "seconds" number of times and then set the label to indicate
    // the countdown has ended
    [self runAction:[SKAction repeatAction:updateLabelAndWait count:seconds] completion:^{
        countDown.text = @"Time's Up";
    }];
}

and then call the method with the duration (in seconds) and the label's position/size.

CGPoint location = CGPointMake (CGRectGetMidX(self.view.frame),CGRectGetMidY(self.view.frame));
[self createTimerWithDuration:20 position:location andSize:24.0];

sprite kit - Label not changing countdown timer SpriteKit Objective C?...

objective-c sprite-kit sklabelnode
Rectangle 27 0

I would not use the update method. Use SKActions to make a timer. For an example

id wait = [SKAction waitForDuration:1];
id run = [SKAction runBlock:^{
    // After a second this is called
}];
[node runAction:[SKAction sequence:@[wait, run]]];

Even though this will only run once, you can always embed this in an SKActionRepeatForever if you want to be called every second or whatever time interval. Source: Spritekit - Creating a timer

I am not sure how I can implement this with the code above

So where ever you want to start your timer. Create an action that waits (with whatever time interval you want). Then the second action is what you want to do once you have waited x amount of time. You could place your setting of the countdown label code inside that run block and decrease an int somewhere that holds the current time. Then make another action that repeats those actions forever. Have a check inside the same code block as your label that says if currentTime <= 0, then stop the actions.

Wait sorry for bothering you, what object should I put as the node?

sprite kit - Label not changing countdown timer SpriteKit Objective C?...

objective-c sprite-kit sklabelnode
Rectangle 27 0

You can keep reference of the time you start the timer. Then, when you want to add extra time, calculate how much time has passed since the timer started, invalidate the timer and create a new one passing as time interval the difference between the time left of the previous timer and the extra seconds.

objective c - How to add time to a countdown timer to iOS Project - St...

ios objective-c nstimer