zoukankan      html  css  js  c++  java
  • iOS 在cell中使用倒计时的处理方法(新)

    一.前言

    之前的文章iOS 在cell中使用倒计时的处理方法得到大量的支持, 在这先感谢大家的支持. 但是也收到不少人的回复表示不会用, 需要一一解答, 由于之前写的时候没有使用Markdown编辑, 所以现在没法更新之前的文章, 重新写一份清晰的文章

    需求: 每条Cell中显示倒计时, 并随时间进行倒数
    语言: Objective-C & Swift
    系统: 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初始化中监听通知 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方法, 保证及时刷新

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

    倒计时为0后出现复用问题

    在倒计时为0后, 应该回调给控制器, 从后台请求一次数据, 保证倒计时没有出现误差

    if (countDown <= 0) {
              // 倒计时结束时回调
              xxxx(使用代理或block)
        }return;

    出现每秒倒计时减2的问题

    1.查看定时器设置是否正确, 或者通知是否监听了两次
    2.在countDownNotification方法中, 是否用[NSDate date]做了某些计算, 因为[NSDate date]为当前时间, 每一秒去取都会比上一秒大一秒, 再加上timeInterval也是一秒加一, 那么就会出现每秒倒计时减2的问题

    如果还有不懂的问题, 或者出现其它bug
    请查看Demo: Demo
    或者给我留言, 喜欢的话, 就给作者一个star



    作者:大头herob
    链接:https://www.jianshu.com/p/af62a56ef7e2
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
     
     
     
  • 相关阅读:
    看K线学炒股(8.10)
    看K线学炒股(8.9)
    看K线学炒股(8.5)
    看K线学炒股(0803)
    看K线学炒股(7.29)
    看K线学炒股(7.21)
    看K线学炒股(2021.07.20)
    看K线学炒股
    说说英力特这只股票
    matlab里的数据转换到Python中去的一个问题
  • 原文地址:https://www.cnblogs.com/SUPER-F/p/9034958.html
Copyright © 2011-2022 走看看