Question

I'm trying to create a simple countdown timer app for myself. So far I've figured out how to create the countdown timers with a stop/reset action on them for a single button I've got attached to the timer.

However, I would like to add multiple timers to the same page and I'm not really sure how to do about making extra calls for the timers. Each of the timers would have it's own number to count down from (7 minutes for one, 3 minutes for the other, etc). These are set intervals that the user is not able to change. Google hasn't really worked out for me on how to do this so I'm hoping someone can at least guide me in the right direction. Below is my code snippets:

ViewController.h

@interface ViewController : UIViewController {
    IBOutlet UILabel *firstCountdownLabel;
    NSTimer *firstCountdownTimer;
    bool timerActive;
    int secondsCount;
}

- (IBAction)start:(id)sender;
- (void)timerRun;

@end

ViewController.m

@interface ViewController ()

@end

@implementation ViewController

- (void) timerRun {
    secondsCount = secondsCount - 1;
    int minutes = secondsCount / 60;
    int seconds = secondsCount - (minutes * 60);

    NSString *timerOutput = [NSString stringWithFormat:@"%2d:%.2d", minutes, seconds];
    firstCountdownLabel.text = timerOutput;

    if (secondsCount == 0) {
        [firstCountdownTimer invalidate];
        firstCountdownTimer = nil;
    }
}

//- (void) setTimer {
- (IBAction)start:(id)sender {
    secondsCount = 420;
    if (timerActive == NO) {
        timerActive = YES;
    self->firstCountdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
}
    else {
        timerActive=NO;
        [self->firstCountdownTimer invalidate];
        self->firstCountdownTimer = nil;
    }
    }

- (void)viewDidLoad
{
    [super viewDidLoad];
//    [self setTimer];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
Was it helpful?

Solution

Google doesn't help in showing you how to implement original application ideas.

If you want multiple timers, define multiple timer instance variables:

@interface ViewController : UIViewController 
{
    IBOutlet UILabel *timer1Label;
    IBOutlet UILabel *timer2Label;
    IBOutlet UILabel *timer3Label;
    NSTimer *timer1;
    NSTimer *timer2;
    NSTimer *timer3;
    int timer1Count;
    int timer2Count;
    int timer3Count;
    bool timer1Active;
    bool timer2Active;
    bool timer3Active;
}

Then create a separate IBAction for each button that starts each of the timers:

- (IBAction)startTimer1:(id)sender 
{
    timer1Count = 420;
    if (timer1Active == NO) 
    {
        timer1Active = YES;
   timer1 = [NSTimer scheduledTimerWithTimeInterval:1.0 
              target:self 
              selector:@selector(timer1Run:) 
              userInfo:nil 
              repeats:YES];
    }
    else 
    {
        timer1Active=NO;
        [timer1 invalidate];
        timer1 = nil;
    }
}

- (void) timer1Run: (NSTimer*) timer
{
    timer1Count -= 1;
    int minutes = timer1Count / 60;
    int seconds = timer1Count - (minutes * 60);

    NSString *timerOutput = [NSString stringWithFormat:@"%2d:%.2d", minutes, seconds];
    timer1Label = timerOutput;

    if (timer1Count == 0) {
        [timer2 invalidate];
        timer2 = nil;
    }
}

Duplicate the above code for each timer, using "timer2" and "timer3" in place of "timer1". Change the time counts for each one to the desired values. (I changed the names from "firstTimer" to "timer1" because it's easier to edit the code to support multiple timers that way.

I did not write 3 versions of each method for you because you need to figure this out rather than copy & pasting in code that you don't understand.

It would be possible, and require less code, to use the same IBAction method for all your start timer buttons, and have the code check the tag on the button to decide which timer to start.

The code might look like this:

- (IBAction)startTimer1:(id)sender 
{
  int tag = [sender tag];
  switch (tag)
  {
  case 1: //timer 1
    //Put code to start timer 1 here
    break;
  case 2: //timer 2
    //put code to start timer 2 here
    break;
  }
} 

But that might be a bit over your head at the moment.

By the way, forget you ever saw the "self->variable" syntax. it is slower and more error-prone than just referring to the instance variable directly. using object->variable syntax also allows you to access the instance variables of other objects, which is bad practice. You should always use properties to access the instance variables of objects other than yourself.

Also, the timer method should take a single parameter, a timer. I corrected the timer method in the above code.

OTHER TIPS

Create a class as YourTimer with few properties like

NSString *timerLabel;
NSTimer *timer;
NSInteger timerCounter;

Now create an array of YourTimer objects. Then you can access it easily.

This will be modular, maintainable and reusable code, as may be later on you need one more identifier to be with all timers, hence wrap them in one class and use it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top