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

一.前言

以前的文章iOS 在cell中使用倒計時的處理方法獲得大量的支持, 在這先感謝你們的支持. 可是也收到很多人的回覆表示不會用, 須要一一解答, 因爲以前寫的時候沒有使用Markdown編輯, 因此如今無法更新以前的文章, 從新寫一份清晰的文章git

需求: 每條Cell中顯示倒計時, 並隨時間進行倒數
語言: Objective-C & Swift
系統: iOS
Github地址: OYCountDownManager v2.0
OYCountDownManager-Swift v2.0github

二.原理分析

 
原理分析圖.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初始化中監聽通知 kCountDownNotification

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

 

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

- (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. 當刷新數據時,調用reload方法

- (void)reloadData {
    // 網絡加載數據

    // 調用[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取得時間差, 根據時間差進行處理

- (void)countDownNotification {
    /// 判斷是否須要倒計時 -- 可能有的cell不須要倒計時,根據真實需求來進行判斷
    if (0) {
        return;
    }
    /// 計算倒計時
    OYModel *model = self.model;
    /// 根據identifier取得時間差, 以OYMultipleTableSource1爲例
    NSInteger timeInterval = timeInterval = [kCountDownManager timeIntervalWithIdentifier: OYMultipleTableSource1];
    }
    NSInteger countDown = model.count - timeInterval;
    /// 當倒計時到了進行回調
    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. 當刷新數據時,調用reloadSourceWithIdentifier:刷新時間差

- (void)reloadData {
    // 網絡加載數據

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

 

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

- (void)reloadData {
    // 網絡加載數據

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

 

五.注意事項

偏差分析

  • NSTimer能夠精確到50-100毫秒,不是絕對準確的,因此使用時間累加的方法時間久了有可能成爲時間偏差的來源
  • 爲秒爲單位觸發定時器, 當reloadData後, 定時器也許恰好到達觸發點, 時間差+1, 數據剛reload完就立刻-1秒
  • 後臺模式是以進入後臺的本地時間, 及進入前臺的本地時間作差值來計算的, 當用戶手動修改本地時間, 也會成爲時間差錯誤的來源之一, 若是能在進入前臺的時間再從服務器取一次數據, 或者記錄服務器時間而不是本地時間, 也能夠避免這一偏差

滾動cell時出去文字閃爍

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

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

 

倒計時爲0後出現複用問題

在倒計時爲0後, 應該回調給控制器, 從後臺請求一次數據, 保證倒計時沒有出現偏差spa

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

 

出現每秒倒計時減2的問題

1.查看定時器設置是否正確, 或者通知是否監聽了兩次
2.在countDownNotification方法中, 是否用[NSDate date]作了某些計算, 由於[NSDate date]爲當前時間, 每一秒去取都會比上一秒大一秒, 再加上timeInterval也是一秒加一, 那麼就會出現每秒倒計時減2的問題3d

若是還有不懂的問題, 或者出現其它bug
請查看Demo: Demo
或者給我留言, 喜歡的話, 就給做者一個star代理



做者: 大頭herob
連接: https://www.jianshu.com/p/af62a56ef7e2 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索