#import <Foundation/Foundation.h> [@protocol](https://my.oschina.net/u/819710) TimeCountDownDelegate @optional //顯示倒計時 - (void)showTime:(NSInteger)atime; [@end](https://my.oschina.net/u/567204) [@interface](https://my.oschina.net/u/996807) TimeCountDown : NSObject { NSTimer *aTimer; //計時器間隔 NSTimeInterval aTimeInterval; id<TimeCountDownDelegate> delegate; NSInteger timecount; } [@property](https://my.oschina.net/property) (nonatomic,strong) id<TimeCountDownDelegate> delegate; @property (nonatomic,assign) NSInteger timecount; //傳入時間是秒 - (void)setTimeInterval:(NSInteger)interval anddelegaate:(id)adeletage; +(TimeCountDown *)sharedRegisterTimeCountDown; +(TimeCountDown *)sharedResetpasswordTimeCountDown; - (void)showTime; @end #import "TimeCountDown.h" @implementation TimeCountDown @synthesize delegate; @synthesize timecount; static TimeCountDown * registerTimeCountDown = nil; static TimeCountDown * resetPasswordTimeCountDown = nil; - (id)init { if(self = [super init]) { timecount = 0; } return self; } - (void)startTime { aTimer = [NSTimer scheduledTimerWithTimeInterval:aTimeInterval target:self selector:@selector(showTime) userInfo:nil repeats:YES]; } - (void)stopTime { [aTimer invalidate]; aTimer = nil; } - (void)setTimeInterval:(NSInteger)interval anddelegaate:(id)adeletage { if (timecount <= 0) { timecount = interval; self.delegate = adeletage; aTimeInterval = 1; [self startTime]; } } +(TimeCountDown *)sharedRegisterTimeCountDown { @synchronized(self) { if (registerTimeCountDown == nil) { registerTimeCountDown = [[TimeCountDown alloc] init]; } } return registerTimeCountDown; } +(TimeCountDown *)sharedResetpasswordTimeCountDown { @synchronized(self) { if (resetPasswordTimeCountDown == nil) { resetPasswordTimeCountDown = [[TimeCountDown alloc] init]; } } return resetPasswordTimeCountDown; } - (void)showTime { timecount--; if (timecount >= 0) { if (self.delegate) { [self.delegate showTime:timecount]; } }else{ [self stopTime]; } } @end //調用 #import "ViewController.h" #import "TimeCountDown.h" #define MESSAGE_COUNTDOWN 10 @interface ViewController ()<TimeCountDownDelegate> @property (nonatomic,strong) TimeCountDown * timeCountDown; @property (nonatomic,strong) UIButton *messageBtn; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.messageBtn]; self.timeCountDown = [TimeCountDown sharedRegisterTimeCountDown]; _timeCountDown.delegate = self; } -(void)messageSendBtnTapped:(id) btn{ [self.timeCountDown setTimeInterval:MESSAGE_COUNTDOWN anddelegaate:self]; } #pragma mark-SearchTime - (void)showTime:(NSInteger)atime { if (self.timeCountDown.timecount > 0) { [self.messageBtn setTitle:[NSString stringWithFormat:@"%td秒",atime] forState:UIControlStateNormal]; self.messageBtn.userInteractionEnabled = NO; }else{ [self.messageBtn setTitle:@"獲取" forState:UIControlStateNormal]; self.messageBtn.userInteractionEnabled = YES; } } -(UIButton *)messageBtn{ if (!_messageBtn){ _messageBtn = [[UIButton alloc]init]; _messageBtn.frame = CGRectMake(100, 100, 50, 50); [_messageBtn setTitle:@"獲取" forState:UIControlStateNormal]; _messageBtn.layer.cornerRadius = 3.0f; _messageBtn.clipsToBounds = YES; _messageBtn.titleLabel.font = [UIFont boldSystemFontOfSize:16]; [_messageBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal]; [_messageBtn addTarget:self action:@selector(messageSendBtnTapped:) forControlEvents:UIControlEventTouchUpInside]; } return _messageBtn; } @end
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface CountDown : NSObject ///用NSDate日期倒計時 -(void)countDownWithStratDate:(NSDate *)startDate finishDate:(NSDate *)finishDate completeBlock:(void (^)(NSInteger day,NSInteger hour,NSInteger minute,NSInteger second))completeBlock; ///用時間戳倒計時 -(void)countDownWithStratTimeStamp:(long long)starTimeStamp finishTimeStamp:(long long)finishTimeStamp completeBlock:(void (^)(NSInteger day,NSInteger hour,NSInteger minute,NSInteger second))completeBlock; ///每秒走一次,回調block -(void)countDownWithPER_SECBlock:(void (^)())PER_SECBlock; -(void)destoryTimer; -(NSDate *)dateWithLongLong:(long long)longlongValue; @end
#import "CountDown.h" @interface CountDown () @property(nonatomic,retain) dispatch_source_t timer; @property(nonatomic,retain) NSDateFormatter *dateFormatter; @end @implementation CountDown - (instancetype)init{ self = [super init]; if (self) { self.dateFormatter=[[NSDateFormatter alloc] init]; [self.dateFormatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; NSTimeZone *localTimeZone = [NSTimeZone localTimeZone]; [self.dateFormatter setTimeZone:localTimeZone]; } return self; } -(void)countDownWithStratDate:(NSDate *)startDate finishDate:(NSDate *)finishDate completeBlock:(void (^)(NSInteger day,NSInteger hour,NSInteger minute,NSInteger second))completeBlock{ if (_timer==nil) { NSTimeInterval timeInterval =[finishDate timeIntervalSinceDate:startDate]; __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; dispatch_async(dispatch_get_main_queue(), ^{ completeBlock(0,0,0,0); }); }else{ int days = (int)(timeout/(3600*24)); int hours = (int)((timeout-days*24*3600)/3600); int minute = (int)(timeout-days*24*3600-hours*3600)/60; int second = timeout-days*24*3600-hours*3600-minute*60; dispatch_async(dispatch_get_main_queue(), ^{ completeBlock(days,hours,minute,second); }); timeout--; } }); dispatch_resume(_timer); } } } -(void)countDownWithPER_SECBlock:(void (^)())PER_SECBlock{ if (_timer==nil) { 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, ^{ dispatch_async(dispatch_get_main_queue(), ^{ PER_SECBlock(); }); }); dispatch_resume(_timer); } } -(NSDate *)dateWithLongLong:(long long)longlongValue{ long long value = longlongValue/1000; NSNumber *time = [NSNumber numberWithLongLong:value]; //轉換成NSTimeInterval,用longLongValue,防止溢出 NSTimeInterval nsTimeInterval = [time longLongValue]; NSDate *date = [[NSDate alloc] initWithTimeIntervalSince1970:nsTimeInterval]; return date; } -(void)countDownWithStratTimeStamp:(long long)starTimeStamp finishTimeStamp:(long long)finishTimeStamp completeBlock:(void (^)(NSInteger day,NSInteger hour,NSInteger minute,NSInteger second))completeBlock{ if (_timer==nil) { NSDate *finishDate = [self dateWithLongLong:finishTimeStamp]; NSDate *startDate = [self dateWithLongLong:starTimeStamp]; NSTimeInterval timeInterval =[finishDate timeIntervalSinceDate:startDate]; __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; dispatch_async(dispatch_get_main_queue(), ^{ completeBlock(0,0,0,0); }); }else{ int days = (int)(timeout/(3600*24)); int hours = (int)((timeout-days*24*3600)/3600); int minute = (int)(timeout-days*24*3600-hours*3600)/60; int second = timeout-days*24*3600-hours*3600-minute*60; dispatch_async(dispatch_get_main_queue(), ^{ completeBlock(days,hours,minute,second); }); timeout--; } }); dispatch_resume(_timer); } } } /** * 獲取當天的年月日的字符串 * @return 格式爲年-月-日 */ -(NSString *)getNowyyyymmdd{ NSDate *now = [NSDate date]; NSDateFormatter *formatDay = [[NSDateFormatter alloc] init]; formatDay.dateFormat = @"yyyy-MM-dd"; NSString *dayStr = [formatDay stringFromDate:now]; return dayStr; } /** * 主動銷燬定時器 * @return 格式爲年-月-日 */ -(void)destoryTimer{ if (_timer) { dispatch_source_cancel(_timer); _timer = nil; } } -(void)dealloc{ NSLog(@"%s dealloc",object_getClassName(self)); } @end
// // CountDownViewController.m // 倒計時 // // Created by Maker on 16/7/5. // Copyright © 2016年 鄭文明. All rights reserved. // #import "CountDownViewController.h" #import "Masonry.h" #import "UIView+ArrangeSubview.h" #import "CountDown.h" @interface CountDownViewController () @property (strong, nonatomic) UILabel *dayLabel; @property (strong, nonatomic) UILabel *hourLabel; @property (strong, nonatomic) UILabel *minuteLabel; @property (strong, nonatomic) UILabel *secondLabel; @property (strong, nonatomic) UIView *contentView; @property (strong, nonatomic) UIButton *timeBtn; @property (strong, nonatomic) CountDown *countDownForBtn; @property (strong, nonatomic) CountDown *countDownForLabel; @end @implementation CountDownViewController /** * 獲取當天的年月日的字符串 * 這裏測試用 * @return 格式爲年-月-日 */ -(NSString *)getyyyymmdd{ NSDate *now = [NSDate date]; NSDateFormatter *formatDay = [[NSDateFormatter alloc] init]; formatDay.dateFormat = @"yyyy-MM-dd"; NSString *dayStr = [formatDay stringFromDate:now]; return dayStr; } ///佈局UI -(void)initUI{ CGFloat label_width = 60; CGFloat label_Height = 40; self.contentView = [UIView new]; self.contentView.backgroundColor = [UIColor magentaColor]; [self.view addSubview:self.contentView]; [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(4*label_width, label_Height)); make.center.equalTo(self.view); }]; self.dayLabel = [UILabel new]; self.dayLabel.textAlignment = NSTextAlignmentCenter; self.dayLabel.backgroundColor = [UIColor cyanColor]; self.dayLabel.font = [UIFont systemFontOfSize:15]; [self.contentView addSubview:self.dayLabel]; self.hourLabel = [UILabel new]; self.hourLabel.textAlignment = NSTextAlignmentCenter; self.hourLabel.font = [UIFont systemFontOfSize:15]; self.hourLabel.backgroundColor = [UIColor greenColor]; [self.contentView addSubview:self.hourLabel]; self.minuteLabel = [UILabel new]; self.minuteLabel.textAlignment = NSTextAlignmentCenter; self.minuteLabel.font = [UIFont systemFontOfSize:15]; self.minuteLabel.backgroundColor = [UIColor redColor]; [self.contentView addSubview:self.minuteLabel]; self.secondLabel = [UILabel new]; self.secondLabel.textAlignment = NSTextAlignmentCenter; self.secondLabel.font = [UIFont systemFontOfSize:15]; self.secondLabel.backgroundColor = [UIColor orangeColor]; [self.contentView addSubview:self.secondLabel]; [self.dayLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(@[self.hourLabel,self.minuteLabel,self.secondLabel]); make.top.equalTo(self.contentView); make.width.mas_equalTo(label_width); make.height.equalTo(self.contentView); }]; [self.hourLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.size.equalTo(self.dayLabel); }]; [self.minuteLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.size.equalTo(self.dayLabel); }]; [self.secondLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.size.equalTo(self.dayLabel); }]; [self.contentView arrangeSubviewWithSpacingHorizontally:@[self.dayLabel,self.hourLabel,self.minuteLabel,self.secondLabel]]; self.timeBtn = [UIButton buttonWithType:UIButtonTypeCustom]; self.timeBtn.backgroundColor = [UIColor redColor]; [self.timeBtn setTitle:@"點擊獲取驗證碼" forState:UIControlStateNormal]; [self.timeBtn addTarget:self action:@selector(fetchCoder:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.timeBtn]; [self.timeBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(self.contentView); make.left.mas_equalTo(self.contentView); make.bottom.mas_equalTo(self.contentView.mas_top).offset(-40); }]; UIButton *nextPageBtn = [UIButton buttonWithType:UIButtonTypeCustom]; nextPageBtn.backgroundColor = [UIColor redColor]; [nextPageBtn setTitle:@"push到下一頁" forState:UIControlStateNormal]; [nextPageBtn addTarget:self action:@selector(nextPage:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:nextPageBtn]; [nextPageBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(self.timeBtn); make.left.mas_equalTo(self.timeBtn); make.bottom.mas_equalTo(self.timeBtn.mas_top).offset(-40); }]; } -(void)nextPage:(UIButton *)sender{ UIViewController *aVC = [[UIViewController alloc]init]; aVC.view.backgroundColor = [UIColor whiteColor]; [self.navigationController pushViewController:aVC animated:YES]; } -(void)fetchCoder:(UIButton *)sender{ // 60s的倒計時 // NSTimeInterval aMinutes = 60; // 1個小時的倒計時 // NSTimeInterval anHour = 60*60; // 1天的倒計時 NSTimeInterval aDay = 24*60*60; [self startWithStartDate:[NSDate date] finishDate:[NSDate dateWithTimeIntervalSinceNow:aDay]]; } #pragma mark #pragma mark viewDidLoad - (void)viewDidLoad { [super viewDidLoad]; [self initUI]; self.view.backgroundColor = [UIColor whiteColor]; _countDownForLabel = [[CountDown alloc] init]; _countDownForBtn = [[CountDown alloc] init]; ///方法一倒計時測試 long long startLongLong = 1467713971000; // long long finishLongLong = 1467714322000; long long finishLongLong = 1467755322000; [self startLongLongStartStamp:startLongLong longlongFinishStamp:finishLongLong]; NSDateFormatter* formater = [[NSDateFormatter alloc] init]; [formater setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSDate* startDate = [formater dateFromString:@"2018-12-31 08:23:20"]; NSDate* finishDate = [formater dateFromString:@"2019-1-1 00:00:00"]; // [self startWithStartDate:startDate finishDate:finishDate]; } -(void)refreshUIDay:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second{ if (day==0) { self.dayLabel.text = @"0天"; }else{ self.dayLabel.text = [NSString stringWithFormat:@"%ld天",(long)day]; } if (hour<10&&hour) { self.hourLabel.text = [NSString stringWithFormat:@"0%ld小時",(long)hour]; }else{ self.hourLabel.text = [NSString stringWithFormat:@"%ld小時",(long)hour]; } if (minute<10) { self.minuteLabel.text = [NSString stringWithFormat:@"0%ld分",(long)minute]; }else{ self.minuteLabel.text = [NSString stringWithFormat:@"%ld分",(long)minute]; } if (second<10) { self.secondLabel.text = [NSString stringWithFormat:@"0%ld秒",(long)second]; }else{ self.secondLabel.text = [NSString stringWithFormat:@"%ld秒",(long)second]; } } ///此方法用兩個時間戳作參數進行倒計時 -(void)startLongLongStartStamp:(long long)strtLL longlongFinishStamp:(long long)finishLL{ __weak __typeof(self) weakSelf= self; [_countDownForLabel countDownWithStratTimeStamp:strtLL finishTimeStamp:finishLL completeBlock:^(NSInteger day, NSInteger hour, NSInteger minute, NSInteger second) { NSLog(@"666"); [weakSelf refreshUIDay:day hour:hour minute:minute second:second]; }]; } //此方法用兩個NSDate對象作參數進行倒計時 -(void)startWithStartDate:(NSDate *)strtDate finishDate:(NSDate *)finishDate{ __weak __typeof(self) weakSelf= self; [_countDownForBtn countDownWithStratDate:strtDate finishDate:finishDate completeBlock:^(NSInteger day, NSInteger hour, NSInteger minute, NSInteger second) { NSLog(@"second = %li",second); NSInteger totoalSecond =day*24*60*60+hour*60*60 + minute*60+second; if (totoalSecond==0) { weakSelf.timeBtn.enabled = YES; [weakSelf.timeBtn setTitle:@"從新獲取驗證碼" forState:UIControlStateNormal]; }else{ weakSelf.timeBtn.enabled = NO; [weakSelf.timeBtn setTitle:[NSString stringWithFormat:@"%lis後從新獲取",totoalSecond] forState:UIControlStateNormal]; } }]; } -(void)dealloc{ [_countDownForLabel destoryTimer]; [_countDownForBtn destoryTimer]; NSLog(@"%s dealloc",object_getClassName(self)); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end