有时候需要时间验证码倒计时,以前在没有使用rac
的时候我是这么写的:
__block int timeout = [time intValue];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(_timer, ^{
if(timeout<=0){
dispatch_source_cancel(_timer);
dispatch_async(dispatch_get_main_queue(), ^{
// 倒计时完成
[self.codeButton setTitle:@"获取验证码" forState:UIControlStateNormal];
self.codeButton.enabled = YES;
});
}else{
int seconds = timeout;
NSString *strTime = [NSString stringWithFormat:@"%.2d", seconds];
dispatch_async(dispatch_get_main_queue(), ^{
// 更新button上的倒计时
[self.codeButton setTitle:[NSString stringWithFormat:@"%@秒后重新获取",strTime] forState:UIControlStateNormal];
self.codeButton.enabled = NO;
});
timeout--;
}
});
dispatch_resume(_timer);
用GCD这么写比较蛋疼,更好的办法,肯定有的,但是因为项目的原因没有再研究,直到用到了ReactiveCocoa
后,我不由得思考,如何更简单的实现这个功能:
- 将倒计时本身给抽取出来;
-
将按钮的
enabled
给独立出来;@weakify(self); static NSInteger number = 0; RACSignal *timerSignal = [[[RACSignal interval:1.0f onScheduler:[RACScheduler mainThreadScheduler]] map:^id(NSDate *date){ @strongify(self); if (--number <= 0) { [self.codeButton setTitle:@"获取验证码" forState:UIControlStateNormal]; return @YES; }else{ [self.codeButton setTitle:[NSString stringWithFormat:@"%d秒后可重新获取", (int)number] forState:UIControlStateNormal]; return @NO; } }] takeUntilBlock:^BOOL(id x){ return number <= 0; }]; // 验证码点击 self.regView.codeButton.rac_command = [[RACCommand alloc]initWithSignalBlock:^RACSignal *(id input) { number = kCountDownSeconds; return timerSignal; }];
好处一目了然。