【发布时间】:2011-05-24 15:08:06
【问题描述】:
我想使用 UILabel 显示倒计时计时器,该计时器将从 5 开始并每秒减少 1,例如:
5 4 3 2 1
最后在达到0时隐藏标签。
我尝试使用 NSTimer scheduledTimerWithTimeInterval 对其进行编码,但失败了。
请帮帮我。
【问题讨论】:
-
向我们展示失败的代码。
我想使用 UILabel 显示倒计时计时器,该计时器将从 5 开始并每秒减少 1,例如:
5 4 3 2 1
最后在达到0时隐藏标签。
我尝试使用 NSTimer scheduledTimerWithTimeInterval 对其进行编码,但失败了。
请帮帮我。
【问题讨论】:
我只是在做类似的事情。我的代码中有一个名为 timeReamin 的 UILabel。它每秒更新一次,直到达到 0,然后显示警报。我必须警告您,由于计时器与您的 UI 在同一线程上运行,您可能会遇到一些抖动。我还没有解决这个问题,但这适用于简单的计时器。这是我正在使用的代码:
- (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];
这确保线程将无限期地执行。您可以管理计时器,例如重新启动它或在其他方法中将其设置为不同的值。我在代码中的其他地方初始化了计时器,这就是删除该行的原因。
【讨论】:
这是一个使用 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;
}
【讨论】:
这是倒数计时器的最终解决方案。您还可以使用来自网络服务的开始和结束日期,也可以使用当前系统日期。
-(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];
}
}
【讨论】: