iOS 在cell中使用倒計時的處理方法(新)

一.前言

之前的文章iOS 在cell中使用倒計時的處理方法得到大量的支持, 在這先感謝大家的支持. 但是也收到不少人的回復表示不會用, 需要一一解答, 由于之前寫的時候沒有使用Markdown編輯, 所以現(xiàn)在沒法更新之前的文章, 重新寫一份清晰的文章

需求: 每條Cell中顯示倒計時, 并隨時間進行倒數(shù)
語言: Objective-C & Swift
系統(tǒng): iOS
Github地址: OYCountDownManager v2.0
OYCountDownManager-Swift v2.0

二.原理分析

原理分析圖.png

單個列表倒計時.gif

v2.0新增

* 多個列表倒計時
* 多個頁面倒計時
* 分頁列表倒計時
* 后臺模式倒計時
多個列表倒計時.gif
多個頁面倒計時.gif
分頁列表倒計時.gif

三.使用方法

1.1 第一種方法: 使用cocoapods自動安裝

pod 'OYCountDownManager'

1.2 第二種方法

下載示例Demo, 把里面的OYCountDownManager文件夾拖到你的項目中

2. 在第一次使用的地方調用[kCountDownManager start]

- (void)viewDidLoad {
    [super viewDidLoad];

    // 啟動倒計時管理
    [kCountDownManager start];
}

3. 在Cell初始化中監(jiān)聽通知 kCountDownNotification

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        // 監(jiān)聽通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(countDownNotification) name:kCountDownNotification object:nil];
    }
    return self;
}

4. 在cell設置通知回調, 取得時間差, 根據(jù)時間差進行處理

- (void)countDownNotification {
    /// 計算倒計時
    NSInteger countDown = [self.model.count integerValue] - kCountDownManager.timeInterval;
    if (countDown <= 0) {
          // 倒計時結束時回調
          xxxx(使用代理或block)
    }return;
    /// 重新賦值
    self.timeLabel.text = [NSString stringWithFormat:@"倒計時%02zd:%02zd:%02zd", countDown/3600,       (countDown/60)%60, countDown%60];
}

5. 當刷新數(shù)據(jù)時,調用reload方法

- (void)reloadData {
    // 網(wǎng)絡加載數(shù)據(jù)

    // 調用[kCountDownManager reload]
    [kCountDownManager reload];
    // 刷新
    [self.tableView reloadData];
}

6. 當不需要倒計時時, 廢除定時器

[kCountDownManager invalidate];

四.高級使用(多列表.多頁面.分頁列表)

增加identifier:標識符, 一個identifier支持一個倒計時源, 有一個單獨的時間差

/** 添加倒計時源 */
- (void)addSourceWithIdentifier:(NSString *)identifier;

/** 獲取時間差 */
- (NSInteger)timeIntervalWithIdentifier:(NSString *)identifier;

/** 刷新倒計時源 */
- (void)reloadSourceWithIdentifier:(NSString *)identifier;

/** 刷新所有倒計時源 */
- (void)reloadAllSource;

/** 清除倒計時源 */
- (void)removeSourceWithIdentifier:(NSString *)identifier;

/** 清除所有倒計時源 */
- (void)removeAllSource;

以一個頁面有兩個獨立的列表為例

1.定義identifier(常量)

NSString *const OYMultipleTableSource1 = @"OYMultipleTableSource1";
NSString *const OYMultipleTableSource2 = @"OYMultipleTableSource2";

2.增加倒計時源

// 增加倒計時源 
[kCountDownManager addSourceWithIdentifier:OYMultipleTableSource1];
[kCountDownManager addSourceWithIdentifier:OYMultipleTableSource2];

3.在cell通知回調中, 通過identifier取得時間差, 根據(jù)時間差進行處理

- (void)countDownNotification {
    /// 判斷是否需要倒計時 -- 可能有的cell不需要倒計時,根據(jù)真實需求來進行判斷
    if (0) {
        return;
    }
    /// 計算倒計時
    OYModel *model = self.model;
    /// 根據(jù)identifier取得時間差, 以OYMultipleTableSource1為例
    NSInteger timeInterval = timeInterval = [kCountDownManager timeIntervalWithIdentifier: OYMultipleTableSource1];
    }
    NSInteger countDown = model.count - timeInterval;
    /// 當?shù)褂嫊r到了進行回調
    if (countDown <= 0) {
        self.detailTextLabel.text = @"活動開始";
        // 倒計時結束時回調
          xxxx(使用代理或block)
        return;
    }
    /// 重新賦值
    self.detailTextLabel.text = [NSString stringWithFormat:@"倒計時%02zd:%02zd:%02zd", countDown/3600, (countDown/60)%60, countDown%60];
}

4. 當刷新數(shù)據(jù)時,調用reloadSourceWithIdentifier:刷新時間差

- (void)reloadData {
    // 網(wǎng)絡加載數(shù)據(jù)

   // 調用reloadSourceWithIdentifier:刷新時間差
   [kCountDownManager reloadSourceWithIdentifier:OYMultiplePageSource1];
    // 刷新
    [self.tableView reloadData];
}

5. 當頁面銷毀, 移除倒計時源, 或者不需要定時器, 廢除定時器

// 移除所有倒計時源
[kCountDownManager removeAllSource];
// 廢除定時器
[kCountDownManager invalidate];

五.注意事項

誤差分析

  • NSTimer可以精確到50-100毫秒,不是絕對準確的,所以使用時間累加的方法時間久了有可能成為時間誤差的來源
  • 為秒為單位觸發(fā)定時器, 當reloadData后, 定時器也許剛好到達觸發(fā)點, 時間差+1, 數(shù)據(jù)剛reload完就馬上-1秒
  • 后臺模式是以進入后臺的本地時間, 及進入前臺的本地時間做差值來計算的, 當用戶手動修改本地時間, 也會成為時間差錯誤的來源之一, 如果能在進入前臺的時間再從服務器取一次數(shù)據(jù), 或者記錄服務器時間而不是本地時間, 也可以避免這一誤差

滾動cell時出去文字閃爍

在給cell的模型賦值后, 最好手動調用一下countDownNotification方法, 保證及時刷新

///  重寫setter方法
- (void)setModel:(Model *)model {
    _model = model;
    self.titleLabel.text = model.title;
    // 手動調用通知的回調
    [self countDownNotification];
}

倒計時為0后出現(xiàn)復用問題

在倒計時為0后, 應該回調給控制器, 從后臺請求一次數(shù)據(jù), 保證倒計時沒有出現(xiàn)誤差

if (countDown <= 0) {
          // 倒計時結束時回調
          xxxx(使用代理或block)
    }return;

出現(xiàn)每秒倒計時減2的問題

1.查看定時器設置是否正確, 或者通知是否監(jiān)聽了兩次
2.在countDownNotification方法中, 是否用[NSDate date]做了某些計算, 因為[NSDate date]為當前時間, 每一秒去取都會比上一秒大一秒, 再加上timeInterval也是一秒加一, 那么就會出現(xiàn)每秒倒計時減2的問題

如果還有不懂的問題, 或者出現(xiàn)其它bug
請查看Demo: Demo
或者給我留言, 喜歡的話, 就給作者一個star

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容