实现倒计时有三种方式:NStimer、CADisplayLink、dispatch_source_t
NStimer受runloop周期影响,精确度最低。
CADisplayLink 精确度高,但是受屏幕刷新频率影响,目前FPS是60hz。如果苹果官方改了,兼容性差
下面是dispatch_source_t的实现方式,并进行了封装,便于调用
+ (void)initWithGCD:(int)timeValue beginState:(void (^)(NSInteger time))begin endState:(void (^)(void))end { __block NSInteger time = timeValue; 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_TIME_NOW, 1 * NSEC_PER_SEC, 0); dispatch_source_set_event_handler(timer, ^{ if (time <= 0) { dispatch_source_cancel(timer); dispatch_async(dispatch_get_main_queue(), ^{ if (end) { end(); } }); } else { dispatch_async(dispatch_get_main_queue(), ^{ if (begin) { begin(time); } }); time--; } }); dispatch_resume(timer); }
调用方式:
[HZSTimer initWithGCD:60 beginState:^(NSInteger seconds){ [self.codeBtn setTitle:[NSString stringWithFormat:@"%ld秒",(long)seconds] forState:UIControlStateNormal]; self.codeBtn.userInteractionEnabled = NO; NSLog(@"%ld",(long)seconds); } endState:^() { [self.codeBtn setTitle:@"重新发送" forState:UIControlStateNormal]; self.codeBtn.userInteractionEnabled = YES; }];