iPhone: How to code a reducing countdown timer?

前提是你 提交于 2019-12-04 14:09:14

问题


I want to show a countdown timer using a UILabel which will start from 5 and reduces by 1 every second like:

5 4 3 2 1

and finally hides the label when it reaches 0.

I tried to code it using NSTimer scheduledTimerWithTimeInterval but failed miserably.

Please help me.


回答1:


I was just doing something like that. I have a UILabel that is called timeReamin in my code. It's updated every second until it reaches 0 and then an alert is displayed. I must warn you that since the timer runs on the same thread as your UI, you may experience some jitter. I have not solved that problem yet, but this works for simple timers. Here is code that I am using:

- (void)createTimer {       
    // start timer
    gameTimer = [[NSTimer timerWithTimeInterval:1.00 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES] retain];
    [[NSRunLoop currentRunLoop] addTimer:gameTimer forMode:NSDefaultRunLoopMode];
    timeCount = 5; // instance variable
}

- (void)timerFired:(NSTimer *)timer {
    // update label
    if(timeCount == 0){
        [self timerExpired];
    } else {
        timeCount--;
        if(timeCount == 0) {
            // display correct dialog with button
        [timer invalidate];
        [self timerExpired];
         }
    }
    timeRemain.text = [NSString stringWithFormat:@"%d:%02d",timeCount/60, timeCount % 60];
}


- (void) timerExpired {
   // display an alert or something when the timer expires.
}

Figured out a threaded solution that removes the jitter. In the viewDidLoad method or applicationDidFinishLaunching, you need a line such as:

[NSThread detachNewThreadSelector:@selector(createTimer) toTarget:self withObject:nil];

This will launch a thread using the createTimer method. However, you also need to update the createTimer method as well:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
// start timer
gameTimer = [[NSTimer timerWithTimeInterval:1.00 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES] retain];
[[NSRunLoop currentRunLoop] addTimer:gameTimer forMode:NSDefaultRunLoopMode];
[runLoop run];
[pool release];

Most of this is standard thread entry routine stuff. The pool is used for managed memory strategies employed by the thread which. This is not needed if you are using garbage collection, but it does not hurt. The runloop is an event loop that is executed continuously to generate the events when the time elapses every second. There is a runloop in your main thread that is created automatically, this is a runloop that is specific to this new thread. Then notice that there is a new statement at the end:

[runLoop run];

This ensures that the thread will execute indefinitely. You can manage the timer, such as restarting it or setting it for different values within the other methods. I initialize my timer at other places in my code and that is why that line has been removed.




回答2:


Here is an example using scheduledTimerWithTimeInterval. To use:

1. copy the code into your controller
2. Use IB, create on the fly, to wire up a UILabel to countDownLabel and set hidden true
3. call [self startCountDown] when you want the countdown to start (This one counts down from 3 to 0)
4. in the updateTime method fill in the "do whatever part..." when the timer is done.

In your .h:

int countDown;
NSTimer *countDownTimer;
IBOutlet UILabel *countDownLabel;
@property (nonatomic, retain) NSTimer *countDownTimer;
@property(nonatomic,retain) IBOutlet UILabel *countDownLabel;

In your .m

@synthesize countDownTimer, countDownLabel;

- (void) startCountDown {
    countDown = 3;
    countDownLabel.text = [NSString stringWithFormat:@"%d", countDown];
    countDownLabel.hidden = FALSE;
    if (!countDownTimer) {
        self.countDownTimer = [NSTimer scheduledTimerWithTimeInterval:1.00 
                                                               target:self 
                                                             selector:@selector(updateTime:) 
                                                             userInfo:nil 
                                                              repeats:YES];
    }
}

- (void)updateTime:(NSTimer *)timerParam {
    countDown--;
    if(countDown == 0) {
        [self clearCountDownTimer];
        //do whatever you want after the countdown
    }
    countDownLabel.text = [NSString stringWithFormat:@"%d", countDown];
}
-(void) clearCountDownTimer {
    [countDownTimer invalidate];
    countDownTimer = nil;
    countDownLabel.hidden = TRUE;
}



回答3:


This is the final solution for countdown timer. You can also use start and end dates comming from the web service or you can also use current system date.

-(void)viewDidLoad   
{

 self.timer = [NSTimer scheduledTimerWithTimeInterval:(1.0) target:self selector:@selector(updateLabel) userInfo:nil repeats:YES];
 [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

  NSDateFormatter *dateformatter = [[NSDateFormatter alloc] init];
  [dateformatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

 //Date must be assign in date fromat which you describe above in dateformatter
  NSString *strDate = @"PUT_YOUR_START_HERE"; 
  tmpDate = [dateformatter dateFromString:strDate];

   //Date must be assign in date fromat which you describe above in dateformatter  
   NSString *fathersDay = @"PUT_YOUR_END_HERE";
   currentDate = [dateformatter dateFromString:fathersDay];

    timeInterval = [currentDate timeIntervalSinceDate:tmpDate];

}


-(void)updateLabel
{

    if (timeInterval > 0)
    {

        timeInterval--;


        NSLog(@"TimeInterval = %f",timeInterval);


        div_t h = div(timeInterval, 3600);
        int hours = h.quot;
        // Divide the remainder by 60; the quotient is minutes, the remainder
        // is seconds.
        div_t m = div(h.rem, 60);
        int minutes = m.quot;
        int seconds = m.rem;

        // If you want to get the individual digits of the units, use div again
        // with a divisor of 10.

        NSLog(@"%d:%d:%d", hours, minutes, seconds);


       strHrs = ([[NSString stringWithFormat:@"%d",hours] length] > 1)?[NSString stringWithFormat:@"%d",hours]:[NSString stringWithFormat:@"0%d",hours];
       strMin = ([[NSString stringWithFormat:@"%d",minutes] length] > 1)?[NSString stringWithFormat:@"%d",minutes]:[NSString stringWithFormat:@"0%d",minutes];
       strSec = ([[NSString stringWithFormat:@"%d",seconds] length] > 1)?[NSString stringWithFormat:@"%d",seconds]:[NSString stringWithFormat:@"0%d",seconds];



        [lblhh setText:[NSString stringWithFormat:@"%@", strHrs]];
        [lblmm setText:[NSString stringWithFormat:@"%@", strMin]];
        [lblss setText:[NSString stringWithFormat:@"%@", strSec]];

    }
    else
    {

        NSLog(@"Stop");
        [lblhh setText:[NSString stringWithFormat:@"%@", @"00"]];
        [lblmm setText:[NSString stringWithFormat:@"%@", @"00"]];
        [lblss setText:[NSString stringWithFormat:@"%@", @"00"]];

        [self.timer invalidate];

    }



}


来源:https://stackoverflow.com/questions/4428486/iphone-how-to-code-a-reducing-countdown-timer

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!