IOS中倒计时的方式有很多种:
1、使用NSTimer实现倒计时,需要注意的是NSTimer会持有对象,可能造成死锁
2、使用performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#>
3、使用GCD dispatch_after+迭代
4、使用GCD dispatch_source
下面是对使用dispatch_source实现倒计时的封装:
#import <Foundation/Foundation.h>
typedef void(^CountdownTimerBlock)(NSInteger days,NSInteger hours,NSInteger minutes,NSInteger seconds);
@interface CountdownTimer : NSObject
/**
初始化倒计时器
@param timeInterval 倒计时时间戳,以秒计算
@return 返回初始化对象
*/
-(instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval;
/**
启动倒计时
@param timerBlock 倒计时每调用一次执行的block
*/
-(void)startCountdownTimer:(CountdownTimerBlock)timerBlock;
/**
关闭倒计时
*/
-(void)stopCountdownTimer;
@end
#import "CountdownTimer.h"
@interface CountdownTimer(){
dispatch_source_t _timer;
}
@property(nonatomic,assign)NSTimeInterval timeInterval;
@end
@implementation CountdownTimer
-(instancetype)init{
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"must use initWithTimeInterval:(NSTimeInterval)timeInterval instead"
userInfo:nil];
}
-(instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval{
if(self=[super init]){
_timeInterval=timeInterval;
}
return self;
}
-(void)startCountdownTimer:(CountdownTimerBlock)timerBlock{
if(_timer==nil){
__block int timeout = _timeInterval;
if(timeout!=0){
dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
_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);
_timer=nil;
if(timerBlock){
dispatch_async(dispatch_get_main_queue(), ^{
timerBlock(0,0,0,0);
});
}
}else{
int days = (int)(timeout/(3600*24));
int hours = (int)((timeout-days*24*3600)/3600);
int minutes = (int)(timeout-days*24*3600-hours*3600)/60;
int seconds = timeout-days*24*3600-hours*3600-minutes*60;
if(timerBlock){
dispatch_async(dispatch_get_main_queue(), ^{
timerBlock(days,hours,minutes,seconds);
});
}
}
timeout--;
});
dispatch_resume(_timer);
}
}
}
-(void)stopCountdownTimer{
if(_timer){
dispatch_source_cancel(_timer);
_timeInterval=0;
_timer = nil;
}
}
@end
dispatch_after
performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#>
performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#>