今天在敲代碼的時候轰传,出現一個cell復用以及GCD定時器倒計時的功能出現混亂的問題纱昧,由于之前一直使用NSTimer定時器,并未發(fā)現什么問題,這次本著學習使用的心態(tài)侣灶,把GCD搬上來甸祭,不聊出現一些意料之外的問題。
代碼的前置條件:該定時器在cell復用中倒計時
錯誤創(chuàng)建timer對象的方法是:
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue);
正確的創(chuàng)建timer方法應該是這樣:
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
解釋:
錯誤創(chuàng)建的timer方法表示在每次調用倒計時方法startCountDown的時候褥影,都會創(chuàng)建一個全新的timer對象池户,然后放到全局隊列里進行倒計時,假設當前列表有3個cell伪阶,那么第一次調用時(也就是在第一次刷新時)煞檩,全局隊列會接收到3個不同的timer對象,當第二次調用該倒計時方法時栅贴,仍會創(chuàng)建3個與之前不同的timer對象斟湃,以此類推,刷新N次后檐薯,timer對象一共創(chuàng)建了2N個凝赛,此時全局隊列queue中就有2 *N個定時器,在下面的方法 [self.payBtn setTitle:text forState:UIControlStateNormal]; 就會并發(fā)不斷賦值坛缕,payBtn按鈕就會出現混亂閃動的現象墓猎。解決:通過創(chuàng)建全局的timer,在每次調用倒計時方法時赚楚,新對象就會覆蓋舊有對象毙沾,也就是不論調用多少次倒計時方法,一個cell始終只有一個timer對象宠页,timer對象的數量也就和cell數量一致**
下面直接上代碼左胞。
//time傳入的倒計時剩余時間
- (void)startCountDown:(long long)time{
__block long countDownTime = time;
if (countDownTime>0) {
@weakify(self);
//創(chuàng)建一個全局隊列
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), 1 * NSEC_PER_SEC, 0); //每秒執(zhí)行
dispatch_source_set_event_handler(self.timer, ^{
@strongify(self);
if(!self || countDownTime <= 0 ){// 倒計時結束
// 關閉定時器
dispatch_source_cancel(self.timer);
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self);
// 此處處理你需要的倒計時結束時的操作
});
}else{// 倒計時中
NSString* text = [self timeDifferenceWithDelay:countDownTime];
dispatch_async(dispatch_get_main_queue(), ^{
@strongify(self);
[self.payBtn setTitle:text forState:UIControlStateNormal];
});
}
countDownTime--;
});
// 開啟定時器
dispatch_resume(self.timer);
}
}
// 該方法表示當倒計時剩下不超過30分鐘時的操作
-(NSString*)timeDifferenceWithDelay:(long long )delay{
long second = delay % 60;
long minute = delay/60%60;
long hour = delay/3600 %3600;
long day = delay/(24 * 3600);
NSString *str;
if (day== 0 && hour== 0 && minute<30) {
str = [NSString stringWithFormat:@"付款 %02ld:%02ld",minute,second];
}else {
str = [NSString stringWithFormat:@"付款"];
}
NSLog(@"%02ld:%02ld:%02ld:%02ld",day,hour,minute,second);
return str;
}
總結:其實這個問題不是什么大問題,關鍵是是否細心举户,在此記錄一下烤宙,為后來者借鑒!