iPhone: Как закодировать сокращающий таймер обратного отсчета? - PullRequest
3 голосов
/ 13 декабря 2010

Я хочу показать таймер обратного отсчета, используя UILabel, который начинается с 5, а уменьшается на 1 каждую секунду , например:

5 4 3 2 1

и, наконец, скрывает метку, когда она достигает 0.

Я пытался закодировать его, используя NSTimer scheduledTimerWithTimeInterval, но с треском провалился.

Пожалуйста, помогите мне.

Ответы [ 3 ]

8 голосов
/ 18 декабря 2010

Я просто делал что-то подобное. У меня есть UILabel, который называется timeReamin в моем коде. Он обновляется каждую секунду, пока не достигнет 0, а затем отображается предупреждение. Я должен предупредить вас, что, поскольку таймер работает в том же потоке, что и ваш пользовательский интерфейс, вы можете испытывать некоторое дрожание. Я еще не решил эту проблему, но это работает для простых таймеров. Вот код, который я использую:

- (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.
}

Разобрался с резьбовым решением, которое устраняет джиттер. В методе viewDidLoad или applicationDidFinishLaunching вам нужна строка, такая как:

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

Это запустит поток, используя метод createTimer. Однако вам также необходимо обновить метод createTimer:

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

Большинство из них - стандартные подпрограммы ввода потоков. Пул используется для стратегий управляемой памяти, используемых потоком, который. Это не нужно, если вы используете сборщик мусора, но это не повредит. Runloop - это цикл событий, который выполняется непрерывно, чтобы генерировать события, когда время истекает каждую секунду. В вашем основном потоке есть runloop, который создается автоматически, это runloop, специфичный для этого нового потока. Затем обратите внимание, что в конце есть новое утверждение:

[runLoop run];

Это гарантирует, что поток будет выполняться бесконечно. Вы можете управлять таймером, таким как перезапуск или установка других значений в других методах. Я инициализирую свой таймер в других местах моего кода, и именно поэтому эта строка была удалена.

3 голосов
/ 03 февраля 2012

Вот пример с помощью scheduleTimerWithTimeInterval Использовать:

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.

В вашем .h:

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

В твоем .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;
}
1 голос
/ 21 июня 2013

Это окончательное решение для таймера обратного отсчета.Вы также можете использовать даты начала и окончания, поступающие из веб-службы, или использовать текущую системную дату.

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

    }



}
...