demo地址
效果圖
效果圖
1.時間處理
既然是倒計時咬腋,肯定要有一個對比時間,所以為了保證活動倒計時不受修改本機系統(tǒng)時間的影響胖齐,參考對比時間為服務器時間。
獲取服務器時間的方式是在項目的請求管理類中解析到每一次請求的header信息嗽冒,里面一般包含一個時間戳
NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response;
NSDictionary *allHeaders = resp.allHeaderFields;
NSString *dateServer = [allHeaders objectForKey:@"Date"];
例如demo中的allHeaderFields
打印如下:
{
"Content-Encoding" = gzip;
"Content-Length" = 1145;
"Content-Type" = "text/html";
Date = "Wed, 15 Apr 2020 01:58:59 GMT";
Server = bfe;
}
- 需要做的就是存儲每次請求響應中的這個時間戳呀伙,demo封裝好了分類
NSDate+InternetDateTime
,可以直接調(diào)用并存儲最新的時間添坊,以便下次使用
// 記錄服務器時間
NSDate *inputDate = [NSDate dateFromInternetDateTimeString:dateServer formatHint:DateFormatHintRFC822];
if (inputDate) {
[NSDate saveServerTime:inputDate];
}
注意: 計算服務器時間戳的原理就是將請求響應的服務器時間戳和當前本機系統(tǒng)時間戳同時存儲下來剿另。在需要使用服務器時間戳時,同時取出之前存儲的兩個時間戳,計算得到一個差值雨女。然后再獲取本機系統(tǒng)時間戳谚攒,和差值做計算,得到一個比較準確的服務器時間戳氛堕,這個時間戳才是我們倒計時中的參考時間了馏臭。
另外還有一點需要注意的是要監(jiān)聽系統(tǒng)時間發(fā)生變化,當前程序正在運行期間去改變了系統(tǒng)時間的話讼稚,要及時的更新當前時間的計算括儒。可在AppDelegate中實現(xiàn)以下方法
/// 監(jiān)聽系統(tǒng)時間發(fā)生變化
[[NSNotificationCenter defaultCenter] addObserver:object selector:@selector(systemClockChange:) name:NSSystemClockDidChangeNotification object:nil];
/// 監(jiān)聽系統(tǒng)時間發(fā)生變化時锐想,更新存儲的本地時間
-(void)systemClockChange:(id)sender{
double currentLocalTimeStamp = [[NSDate date] timeIntervalSince1970] * 1000;
[[NSUserDefaults standardUserDefaults] setDouble:currentLocalTimeStamp forKey:kLastSaveLocalTimeStamp];
[[NSUserDefaults standardUserDefaults] synchronize];
}
2.倒計時處理
封裝一個倒計時管理類
SYCountDownManager
帮寻,內(nèi)部創(chuàng)建一個計時器,通過傳入的截止時間赠摇,直接生成倒計時時間固逗,并回傳時間模型。時間模型中提供了int
和NSString
兩種數(shù)據(jù)類型藕帜。也可通過SYCountDownManager
生成固定格式的整體倒計時字符串烫罩,例如:9:29:31
關于計時器的選擇,沒有實際測驗耘戚,但根據(jù)網(wǎng)上查找到的資料分析發(fā)現(xiàn)GCD更好些嗡髓,所有選取了GCD實現(xiàn)計時器操漠。也可以通過其它的方式收津,只需替換相關代碼即可
計時器的銷毀,可根據(jù)實際情況調(diào)用
destoryTimer
浊伙。
3.列表處理
- 使用過程中發(fā)現(xiàn)如果列表中同時存在多個倒計時撞秋,滾動頁面時倒計時會在開始出現(xiàn)時有突然的跳動,為了處理這個問題需要在cell將要出現(xiàn)時就提前給控件賦值嚣鄙。如下兩個系統(tǒng)方法中:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath