cell (iOS表格) - 簡單實現一個定時器管理600個倒數計時 - 2.程式碼介紹篇
傳送門:
效果展示http://www.jianshu.com/p/3c49b44e45b4
如何使用: http://www.jianshu.com/p/5b4e0286658a
下載地址: https://github.com/zhYes/YSTimeCountDown
//2018年03月20日09:48:01更新:
//2018年03月20日09:48:01更新:
//2018年03月20日09:48:01更新:
~
有朋友反映出現了倒數計時一萬多天的情況,經過幾次除錯,發現我這裡有一個獲取當前時間時間戳的介面 用來校準伺服器時間和手機當前時間的差值
當這個介面不好用 獲取不到的時候就是這個樣子了 建議讓後臺自己做個介面 來替換YSCountDown.m
裡面的@"http://api.k780.com:88/?app=life.time&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json"
這個介面就好了,即:
注意:1.時間戳單位這裡是秒.2.自己介面取時間戳的key替換.
2018年03月20日@end
2018年03月20日@end
2018年03月20日@end
~
正文:
需求是這樣的,對UITableView中的每個Cell 加入一個倒數計時器的顯示,如下圖:
一、倒數計時的實現
首先計時器這塊,我第一個會想到是用NSTimer定時器,還是用GCD定時器,或者說CADisplayLink定時呢。
經過粗略的比較這裡採用GCD定時器
NSTimer是必須要在run loop已經啟用的情況下使用的否則無效。而只有主執行緒是預設啟動runLoop的。
我們不能保證自己寫的方法不會被人在非同步的情況下呼叫到,所以有時使用NSTimer不是很保險的。
同時 NSTime 的坑比較多,迴圈應用和 RunLoop 那塊的坑都可以開專題啦。
而CADisplayLink相對來說比較適合做介面的不停重繪。
NStimer是在RunLoop的基礎上執行的,然而RunLoop是在GCD基礎上實現的,所以說GCD可算是更加高階。
本著封裝的思想,工具模型.h這裡我們提供一個供外界呼叫的方法 ?
//需要傳入 1.顯示倒數計時的tableView | 2.結束時刻的時間戳字串陣列
- (void)countDownWithPER_SEC: (UITableView*)tableView :(NSArray*)dataList;
常規程式碼: 頻繁會被呼叫的計算顯示時間方法?
// 傳入結束時間 | 計算與當前時間的差值
- (NSString *)getNowTimeWithString:(NSInteger )aTimeString :(NSInteger)startTime{
NSTimeInterval timeInterval = aTimeString - startTime;
// NSLog(@"%f",timeInterval);
int days = (int)(timeInterval/(3600*24));
int hours = (int)((timeInterval-days*24*3600)/3600);
int minutes = (int)(timeInterval-days*24*3600-hours*3600)/60;
int seconds = timeInterval-days*24*3600-hours*3600-minutes*60;
NSString *dayStr;NSString *hoursStr;NSString *minutesStr;NSString *secondsStr;
//天
dayStr = [NSString stringWithFormat:@"%d",days];
//小時
hoursStr = [NSString stringWithFormat:@"%d",hours];
//分鐘
if(minutes<10)
minutesStr = [NSString stringWithFormat:@"0%d",minutes];
else
minutesStr = [NSString stringWithFormat:@"%d",minutes];
//秒
if(seconds < 10)
secondsStr = [NSString stringWithFormat:@"0%d", seconds];
else
secondsStr = [NSString stringWithFormat:@"%d",seconds];
if (hours<=0&&minutes<=0&&seconds<=0) {
return @"活動已經結束!";
}
if (days) {
return [NSString stringWithFormat:@"%@天 %@小時 %@分 %@秒", dayStr,hoursStr, minutesStr,secondsStr];
}
return [NSString stringWithFormat:@"%@小時 %@分 %@秒",hoursStr , minutesStr,secondsStr];
}
- 核心程式碼1: 介面獲得真實的伺服器返回時間,並計算與當前系統時間差值! ?
- (void)setupLess {
AFHTTPSessionManager * manager = [AFHTTPSessionManager manager];
[manager POST:@"http://api.k780.com:88/?app=life.time&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary* responseObject) {
// NSLog(@"%@",responseObject);
NSString * webCurrentTimeStr = responseObject[@"result"][@"timestamp"];
NSInteger webCurrentTime = webCurrentTimeStr.longLongValue;
NSDate * date = [NSDate date];
NSInteger nowInteger = [date timeIntervalSince1970];
_less = nowInteger - webCurrentTime;
NSLog(@" -- 與伺服器時間的差值 -- %zd",_less);
if (_dataList) {
[self destoryTimer];
[self countDownWithPER_SEC:_myTableView :_dataList];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@ - 網路錯誤 ! ",error);
}];
}
- 核心程式碼2:
- 利用定時器,每秒改變當前tableView可見cell需要倒數計時時間的顯示
- 利用
[NSDate date]
每秒遞增與結束時間做差值,這樣每次被GCD定時器調取的時候所顯示的值差1s,出現我們想要的倒數計時效果 - 再利用介面獲取的當前伺服器準確時間與手機系統時間做差值,一次性校準我們的倒數計時 ! 而不是頻繁呼叫介面 ?
- (void)countDownWithPER_SEC :(UITableView*)tableView :(NSArray*)dataList {
_myTableView = tableView;
_dataList = dataList;
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(), ^{
NSArray *cells = tableView.visibleCells; //取出螢幕可見ceLl
for (UITableViewCell *cell in cells) {
NSDate * sjDate = [NSDate date]; //手機時間
NSInteger sjInteger = [sjDate timeIntervalSince1970]; // 手機當前時間戳
NSString* tempEndTime = dataList[cell.tag];
NSInteger endTime = tempEndTime.longLongValue + _less;
cell.textLabel.text = [self getNowTimeWithString:endTime :sjInteger];
if ([cell.textLabel.text isEqualToString:@"活動已經結束!"]) {
cell.textLabel.textColor = [UIColor redColor];
}else{
cell.textLabel.textColor = [UIColor orangeColor];
}
// NSLog(@" -------- %@ ---- %@",cell.detailTextLabel.text,cell.textLabel.text);
}
});
});
dispatch_resume(_timer); // 啟動定時器
}
}
核心程式碼3: 當別人想通過修改本地時間 影響倒數計時時怎麼辦??
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setupLess) name:UIApplicationDidBecomeActiveNotification object:nil];
這裡只需通過通知中心監聽 我們的APP從後臺重新變為前臺
UIApplicationDidBecomeActiveNotification
並重新計算_less
差值 為什麼?
好吧,應該不用解釋
/**
* 主動銷燬定時器
*/
-(void)destoryTimer{
if (_timer) {
dispatch_source_cancel(_timer);
_timer = nil;
}
}
最後一段常規程式碼: 銷燬 ?
========= 任何其他問題,歡迎留言,願與你一起學習?=====
相關文章
- Flutter倒數計時/計時器的實現Flutter
- 面向Vue新人:寫一個簡單的倒數計時按鈕Vue
- 直播系統原始碼,實現倒數計時,定時任務原始碼
- 直播小程式原始碼,vue實現時間倒數計時原始碼Vue
- [Unity]記一個倒數計時介面Unity
- js實現指定時間倒數計時JS
- Flutter 快速上手定時器/倒數計時及實戰講解Flutter定時器
- 一個簡單的時間視窗設計與實現
- 如何使用原生技術寫一個倒數計時時鐘
- 編寫一個簡易計時器程式(edu)
- js自動倒數計時程式碼,倒數計時完畢時自動停止迴圈JS
- 教你玩轉自定義View—手擼一個倒數計時控制元件如此簡單View控制元件
- JavaScript倒數計時程式碼例項JavaScript
- JavaScript 倒數計時60秒程式碼JavaScript
- 倒數計時(Excel程式碼集團)Excel
- 直播電商原始碼,商品出售倒數計時的定時器效果原始碼定時器
- PPT 倒數計時時鐘,用 GIF 動畫實現,可直接使用 -- 附 Python 實現程式碼動畫Python
- Java實現一個簡單的計算器Java
- 簡單介紹Android自定義View實現時鐘功能AndroidView
- ReactiveCocoa 實現 按鈕倒數計時React
- jquery實現60秒倒數計時jQuery
- js實現活動倒數計時JS
- win10 自帶倒數計時如何設定_win10開啟計時器倒數計時的方法Win10
- Flutter系列:2.實現一個簡單的登入介面Flutter
- 微信開發之小程式實現倒數計時
- 小程式 - 驗證碼倒數計時元件元件
- 簡單介紹Shell中的定時任務 crontab
- linux實現一個定時任務Linux
- 一個簡單的區塊鏈程式碼實現區塊鏈
- 用java實現一個簡單的計算器Java
- UniRx精講(一):UniRx簡介&定時功能實現
- JavaScript 前端倒數計時糾偏實現JavaScript前端
- 安卓快速開發框架(十)XBaseAndroid倒數計時,定時器安卓框架Android定時器
- 小程式倒數計時深究
- 一個不用定時器簡易51呼吸燈定時器
- 窺探原理:實現一個簡單的前端程式碼打包器 Roid前端
- 20行程式碼寫一個簡單 Blazor 時鐘元件行程Blazor元件
- iOS-簡單易用的GCD計時器iOSGC
- 使用 Hooks 實現一個簡單的狀態管理器Hook