近日需要实现验证码的倒计时的效果。
虽然NSTimer有些小问题,比如系统处理不过来的时候,NSTimer的运作就会受到影响,但GCD不是很熟悉,还是暂时用NSTimer吧。
基本思路是用NSTimer每秒运行一次一个方法,然后方法里面有个静态变量,每秒钟减1就OK了。
但这样有个问题。这个倒计时需要离开当前界面也要执行。
最开始的想法是写一个计时器,写成单例,每秒钟回调一次。如果只有一个界面用到这个计时器的话,倒没问题,但多个界面的话,每个界面都需要一个独立的计时器。感觉不知道怎么办。
结果是这样解决的:
先定义一个静态的timer,保证无论怎么更换界面,这个timer都没有变。
static NSTimer *timer;
每次进入该界面就执行下面这个方法。每次重新进入一次该界面,都要重新生成一次timer并且执行timerMethod。因为虽然timer一直在执行,但是重新进入之后,timer执行的是之前那个Controller的timerMethod,所以我们要停止这个方法,然后重新给timer赋值,再执行当前这个Controller对象的timerMethod。
- (void)p_startTimer
{
if (timer)
{
[timer invalidate];
timer = nil;
}
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
[timer fire];
}
kICodeTimer是一个静态常量,这里就是一个计数器。
- (void)timerMethod
{
static NSInteger count = kICodeTime;
count--;
NSLog(@"count = %@", @(count));
if (count <= 0)
{
[self p_timerEnd];
[timer invalidate];
timer = nil;
count = kICodeTime;
return;
}
[self p_timerCounting:count];
}
最后有个小提示,如果利用”setTitle: forstate:”来不停更改UIButton的标题的时候,每次更改Button会闪烁。解决办法就是下面这段代码。在前面加上更改Button.titleLabel.text的方法。我看了文档对这个方法的说明,也不理解为什么能解决这个问题。有知道的朋友希望顺便提醒我一下。
- (void)p_timerCounting:(NSInteger)count
{
// 正在倒计时
_iCodeBtn.titleLabel.text = [NSString stringWithFormat:@"%@秒后可重新请求验证码", @(count)];
[_iCodeBtn setTitle:[NSString stringWithFormat:@"%@秒后可重新请求验证码", @(count)] forState:UIControlStateDisabled];
}