How to add time to a countdown timer to iOS Projec

2019-06-08 16:07发布

I have a game where is uses a countdown timer and when the timer is up, you are brougt to a Game over view. I want to add a feature were if they tap a button, it will add like 1, 2 or 3 more seconds to the timer. I already have the code for the timer (Below), but i just need to know how to add more time to the counter. I thought of it and i have to say when the views will switch and it would need to take into a count the added time.

Code:

-(IBAction)Ready:(id)sender {
    [self performSelector:@selector(TimerDelay) withObject:nil afterDelay:1.0];
    [self performSelector:@selector(delay) withObject:nil afterDelay:36.5];
}

-(void)TimerDelay {
    MainInt = 36;

    timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                         target:self
                                       selector:@selector(countDownDuration)
                                       userInfo:nil
                                        repeats:YES];
    if (timer == 0)
    {
        [timer invalidate];
    }
}

-(void)countDownDuration {
    MainInt -= 1;

    seconds.text = [NSString stringWithFormat:@"%i", MainInt];
}

-(void)delay {

    GameOverView1_4inch *second= [self.storyboard instantiateViewControllerWithIdentifier:@"GameOverView1"];
    second.finalScore = self.currentScore;
    [self presentViewController:second animated:YES completion:nil];
}

4条回答
够拽才男人
2楼-- · 2019-06-08 16:47

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.

查看更多
放荡不羁爱自由
3楼-- · 2019-06-08 16:49

Hy, try to use this:

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;
}

the output is similar to this

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

I hope it was helpfull

查看更多
Bombasti
4楼-- · 2019-06-08 16:53

If you're using a timer to manage the game, using a perform selector at the same time (to end the game or anything else) kind of defeats the point and makes the management very complex. Choose one route and stick with it.

When the timer is running, you can change it's fire date using setFireDate:. So, you could get the current fire date, add your time to it and then set the new fire date:

- (void)extendByTime:(NSInteger)seconds
{
    NSDate *newFireDate = [[self.timer fireDate] dateByAddingTimeInterval:seconds];
    [self.timer setFireDate:newFireDate];
}

Then, your button callbacks are something like:

- (void)buttonOnePressed:(id)sender
{
    [self extendByTime:1];
}

- (void)buttonFivePressed:(id)sender
{
    [self extendByTime:5];
}

Once you've removed the performSelector which calls delay your game end will be defined by MainInt reaching zero.

As an aside, don't do this:

if (timer == 0)

The correct approach is:

if (timer == nil)

And if the timer is nil, there's no point in trying to invalidate it...

Also a good idea to take a look at the Objective-C naming guidelines.


Based on your recent comment, it seems that you actually want the timer to continue counting at a second interval, but to add time only to the number of seconds remaining. That's even easier and doesn't require any change to the timer fire date.

- (void)extendByTime:(NSInteger)seconds {
    MainInt += seconds;
    seconds.text = [NSString stringWithFormat:@"%i", MainInt];
}

And you need to add a check in 'countDownDuration':

if (MainInt <= 0) {
    [timer invalidate];
    [self delay];
}

To determine when you're done.

查看更多
We Are One
5楼-- · 2019-06-08 16:56

Here's a library that you can use.

https://github.com/akmarinov/AMClock

查看更多
登录 后发表回答