iOS - 关于每个cell上都出现倒计场景的的研究

背景

以前就有人问过这样一个问题:如果一个tableView的很多或者所有cell上都显示一个倒计时,该怎么实现? 今天自己恰好也遇到了这样的需求:很多产品,每个都有一个时限,在时限内才可以申购,过了申购功能就会关闭.简单描述就是,每个cell上有个倒计时,时间结束与否,点击cell响应的事件是不一样的.那么怎么实现呢?下面谈谈自己的思考过程.


1.Cell内部加一个定时器

  • 既然每个cell都有一个倒计时,时间还可能不一样.根据"高内聚,低耦合"的思想,我首先想着直接让cell自己来实现倒计时功能:每个cell添加一个NSTimer,没隔1秒,让其显示的时间减少一秒.
- (void)timeChange {
    self.totalSeconds --;
    if (self.totalSeconds < 0) {
          self.timerLabel.text = @"倒计时结束";
        return;
    }
    self.timerLabel.text = [self timeChangeWithSeconds:self.totalSeconds];
}
- (void)setDataDict:(NSDictionary *)dataDict {
    _dataDict = dataDict;
    NSString *totalTime = dataDict[@"totalTime"];
    self.totalSeconds = totalTime.integerValue;
    self.timerLabel.text = [self timeChangeWithSeconds:self.totalSeconds];
    if (!_timer) {
        _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
       [[NSRunLoop currentRunLoop] addTimer:_timer forMode:UITrackingRunLoopMode];
    }
}
- (NSString*)timeChangeWithSeconds:(NSInteger)seconds {
    NSInteger temp1 = seconds/60;
    NSInteger temp2 = temp1/ 60;
    NSInteger d = temp2 / 24;
    NSInteger h = temp2 % 24;
    NSInteger m = temp1 % 60;
    NSInteger s = seconds %60;
    NSString * hour =  h< 9 ? [NSString stringWithFormat:@"0%ld",(long)h] :[NSString stringWithFormat:@"%ld",(long)h];
    NSString *day = d < 9 ? [NSString stringWithFormat:@"0%ld",(long)d] :  [NSString stringWithFormat:@"%ld",(long)d];
    NSString *minite =  m < 9 ? [NSString stringWithFormat:@"0%ld",(long)m] :  [NSString stringWithFormat:@"%ld",(long)m];
    NSString *second = s < 9 ? [NSString stringWithFormat:@"0%ld",(long)s] :  [NSString stringWithFormat:@"%ld",(long)s];
    return [NSString stringWithFormat:@"%@天:%@时:%@分:%@秒",day,hour,minite,second];
}
cel内部定时器.png
  • 乍看,好像一切都OK,但是当我们拖动cell时,会发现一旦cell移除屏幕,再拖回来的时候,又会重头倒计时.当然,这和我在setDataDict:方法中的赋值方式有关,可以通过totalSeconds这个属性,保存当前剩余的时间,下一次再进来的时候,去取保存好的值.
- (void)setDataDict:(NSDictionary *)dataDict {
    _dataDict = dataDict;
        if (self.totalSeconds !=0) {
         self.timerLabel.text = [self timeChangeWithSeconds:self.totalSeconds];
    }else {
        NSString *totalTime = dataDict[@"totalTime"];
        self.totalSeconds = totalTime.integerValue;
        self.timerLabel.text = [self timeChangeWithSeconds:self.totalSeconds];
    }
       if (!_timer) {
        _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
       [[NSRunLoop currentRunLoop] addTimer:_timer forMode:UITrackingRunLoopMode];
    }
}
  • 这样做,会发现当cell移除屏幕,再移回来的时候,不再是从头倒计时,但是多拖动几次又会发现新的问题:显示错乱,某个cell出现在了不该出现的位置.
  • 仔细分析不难发现,cell的复用机制是引起上述现象的"罪魁祸首",要解决这个问题,可以让cell不复用,比方说,可以给每个cell绑定不同的标识,达到不复用的目的,看到这里,如果你也是这么想的,那么最好打住,因为为了达到这个目的,而让cell不复用,以牺牲内存占用为代价,无疑是饮鸩止渴,丢了西瓜,捡个芝麻.
  • 值得的注意的是,如果在cell中实现,每个cell都添加一个定时器,这也是一笔可观的开销.

2. 在tableView的parentView中实现

  • 既然在cell中实现遇到的坑比较多,那么又想着在外面做.这样有一个明显的好处,就是只需要一个定时器.每次触发,让每个cell上显示的时间递减.由于tableView的显示,取决于传入的数据,只要我在传入数据之前把需要传的数据处理好,这样就不会因为cell的复用机制而带来显示错乱的问题.运行代码,发现问题圆满解决!
/**定时器触发*/
- (void)timeChange {
    NSMutableArray *tempArrM = [NSMutableArray array];
    for (NSDictionary *dict in self.dataArr) {
        NSString *totalTime = dict[@"totalTime"];
        if ([totalTime isEqualToString:@"0"]) {
             totalTime = @"0";
        }else {
            totalTime = [NSString stringWithFormat:@"%ld",totalTime.integerValue -1];
        }
        [tempArrM addObject:@{@"totalTime":totalTime}];
    }
    self.dataArr = tempArrM;
    [self.pageTableView reloadData];
}

3. 值得注意的几个地方

  • 当我们拖动cell时,如果发现定时器不工作,可以用如下方式解决.
   _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
            [[NSRunLoop currentRunLoop] addTimer:_timer forMode:UITrackingRunLoopMode];
  • ** 关于数据的传入**:
    • 直接提供产品到目前为止还剩多少时间.每个产品对应一个总的时间,用于倒计时.那么,后台给我提供时间时就可以把每个产品对应的总时间返给我们.但是,这样就要求后台自己实时去计算每个产品在我们请求数据时还剩多少时间.
  • 后台把每种产品的截止时间和当前的系统时间返给我们.系统时间,我们可用于矫正自己的系统时间(APP显示的时间是可以人为修改的,并且不通设备之间,iOS与Android之间的时间有可能存在差异,为了统一所以需要矫正),通过矫正好的时间和截止时间,我们就能知道,该产品还剩多少时间.
  • 虽然,我这边自己用的第一种方式写的Demo,但是,相比之下,我更加倾向于第二种数据的传递方式,准确性高,也能为后端同事剩些事.

4. 后记:由于这只是一个最初的Demo,也只是一些个人的初步看法,难免有些疏漏,如有纰漏,还望指正.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,780评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,424评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,397评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,576评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,997评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,945评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,107评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,850评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,625评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,804评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,285评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,613评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,291评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,164评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,963评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,096评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,886评论 2 278

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,643评论 4 59
  • 1.1 谈一谈GCD和NSOperation的区别? 首先二者都是多线程相关的概念,当然在使用中也是根据不同情境进...
    John_LS阅读 1,272评论 0 12
  • 很早我就想写杜牧。想起他,我就会想起崔健的《假行僧》。 我要从南走到北,我还要从白走到黑 我要人们都看到我,但不知...
    c94dc94169e0阅读 267评论 0 0
  • 最近和一个亲戚聊天,她告诉我她过得很苦。丈夫在去年去世,一个人带着孩子,需要养车、上班、养孩子。每个月到手的工资只...
    人在江湖Violet阅读 167评论 0 1
  • 铁道警察学院增援学警自六月初到达杭州以来,一直保持高昂的斗志和积极进取的精神。面对新的工作环境他们选择积极适应,面...
    mzyin阅读 290评论 0 0