前言
最近因为项目中涉及到短信获取验证码功能,并且获取验证码按钮需要显示倒计时功能,同时当从获取验证码界面在倒计时并没有结束的时候返回上一个界面,当前的倒计时按钮状态必须保持在倒计时的状态,在满足上述需求的前提条件下完成了今天所说的CountdownButton,不足之处欢迎大家进行指正。😀
思路
- 实现倒计时需要使用到timer。
- 在倒计时还未结束的时候必须保存当前的状态。
- 为了方便使用使用继承UIButton或者给UIButton添加分类。
实现
timer方面我最开始使用的是NSTimer,但是使用过程中发现引用方面出来了不少的问题,最后换成GCD的Timer来更新时间,具体代码:
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC,0);
__weak typeof(self) WeakSelf = self;
dispatch_source_set_event_handler(_timer, ^{
dispatch_async(dispatch_get_main_queue(), ^{
//在该方法里面更新时间
[WeakSelf updateTime];
});
});
- 保存当前的时间并且第二次启动的时候如果有保存的时间就直接从保存的时间开始倒计时。第二次启动读取时间具体实现代码:
- (void)setSecond:(NSUInteger)second{
//存储当前设置的事件
_totalTime = second;
//获取NSUserDefaults里面存储的时间
NSNumber *time = [self.dfl objectForKey:kSaveTimeKey];
//如果取出时间不为空,就直接启动定时器,并且从当前取出的时间倒计时开始
if (time) {
_second = time.integerValue;
self.fire = YES;
}else{
_second = second;
}
}
在更新时间的方法里面每更新一次就进行一次保存
- (void)updateTime{
_second = _second - 1;
if (_second <= 0) {
//退出定时器
dispatch_source_cancel(_timer);
//定时器设置为nil 第二次启动的时候通过懒加载再次启动timer
_timer = nil;
//移除NSUserDefaults存放的时间
[self.dfl removeObjectForKey:kSaveTimeKey];
self.enabled = YES;
if (_finishCall) {
[self setTitle:_finishCall(self) forState:UIControlStateNormal];
}
_second = _totalTime;
_fire = NO;
}else{
//保存当前的倒计时到NSUserDefaults
[self saveSecond];
if (_titleCall) {
[self setTitle:_titleCall(self,_second) forState:UIControlStateNormal];
}
}
}
不足之处
- 当APP进入后台的情况并没有考虑到;
- 结构代码可能还能进行进一步的精简;
网友评论