You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UITableViewCell独立倒计时异常求助:多Cell共用同一倒计时值

解决UITableView每个Cell独立倒计时的问题

我来帮你搞定这个每个Cell独立倒计时的问题~先看看原代码为啥会出现所有Cell显示同一个倒计时的问题:

  • 你用了全局的currHours、currMinute、currSeconds变量,所有Cell都共享这一组值,循环遍历数组时最后一个元素的倒计时会覆盖前面的,自然所有Cell都显示同一个结果。
  • 在循环里创建NSTimer,会生成多个Timer,但最终只有最后一个会正常工作,而且Timer触发时只更新那一组全局变量,没法做到每个时间点独立递减。

要实现每个Cell对应自己的时间独立倒计时,咱们可以用数据模型+单个全局Timer的方案,具体步骤如下:

1. 创建倒计时数据模型

先新建一个CountdownItem类,用来存储每个倒计时的目标时间、剩余时分秒和显示文本,让每个Cell的状态独立:

// CountdownItem.h
#import <Foundation/Foundation.h>

@interface CountdownItem : NSObject
@property (nonatomic, strong) NSDate *targetDate; // 目标倒计时日期
@property (nonatomic, assign) NSInteger remainingHours;
@property (nonatomic, assign) NSInteger remainingMinutes;
@property (nonatomic, assign) NSInteger remainingSeconds;
@property (nonatomic, copy) NSString *displayText; // 原数组里的时间字符串
@property (nonatomic, assign) BOOL isCompleted; // 是否已经倒计时结束
@end

// CountdownItem.m
#import "CountdownItem.h"

@implementation CountdownItem
@end

2. 修改ViewController的代码

把原来的全局变量和数组替换成模型数组,用单个Timer统一更新所有模型的剩余时间:

// 替换原来的全局变量
@property (nonatomic, strong) NSMutableArray<CountdownItem *> *countdownItems;
@property (nonatomic, strong) NSTimer *countdownTimer;

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 初始化原时间数组
    NSArray *tableData = @[
        @"2018-05-16 06:00:00 p",
        @"2018-05-16 09:00:00 p",
        @"2018-05-16 11:00:00 p",
        @"2018-05-17 02:00:00 a",
        @"2018-05-17 04:00:00 a"
    ];
    
    // 初始化倒计时模型数组
    self.countdownItems = [NSMutableArray array];
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"yyyy-MM-dd hh:mm:ss a"];
    
    for (NSString *timeStr in tableData) {
        CountdownItem *item = [[CountdownItem alloc] init];
        item.displayText = timeStr;
        item.targetDate = [dateFormat dateFromString:timeStr];
        item.isCompleted = NO;
        // 计算初始剩余时间
        [self updateRemainingTimeForItem:item];
        [self.countdownItems addObject:item];
    }
    
    // 启动单个全局Timer,每秒更新一次
    self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateAllCountdowns) userInfo:nil repeats:YES];
}

// 更新单个模型的剩余时间
- (void)updateRemainingTimeForItem:(CountdownItem *)item {
    if (item.isCompleted) return;
    
    NSDate *currentDate = [NSDate date];
    NSTimeInterval timeInterval = [item.targetDate timeIntervalSinceDate:currentDate];
    
    if (timeInterval <= 0) {
        // 倒计时结束
        item.isCompleted = YES;
        item.remainingHours = 0;
        item.remainingMinutes = 0;
        item.remainingSeconds = 0;
        return;
    }
    
    // 计算时分秒
    item.remainingHours = (NSInteger)(timeInterval / 3600);
    timeInterval = fmod(timeInterval, 3600);
    item.remainingMinutes = (NSInteger)(timeInterval / 60);
    item.remainingSeconds = (NSInteger)fmod(timeInterval, 60);
}

// Timer触发时更新所有模型的剩余时间
- (void)updateAllCountdowns {
    BOOL allCompleted = YES;
    for (CountdownItem *item in self.countdownItems) {
        [self updateRemainingTimeForItem:item];
        if (!item.isCompleted) {
            allCompleted = NO;
        }
    }
    
    // 刷新TableView
    [self.tableview reloadData];
    
    // 如果所有倒计时都结束,停止Timer
    if (allCompleted) {
        [self.countdownTimer invalidate];
        self.countdownTimer = nil;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *simpleTableIdentifier = @"Reuse";
    SimpleTableViewCell *cell = (SimpleTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (cell == nil) {
        NSArray *nib =[[NSBundle mainBundle]loadNibNamed:@"SimpleTableViewCell" owner:self options:nil];
        cell=[nib objectAtIndex:0];
    }
    
    CountdownItem *item = self.countdownItems[indexPath.row];
    cell.TimerLabel.text = item.displayText;
    // 显示剩余时间,注意补零
    cell.dynamicTimerLabel.text = [NSString stringWithFormat:@"%02ld:%02ld:%02ld",
                                  (long)item.remainingHours,
                                  (long)item.remainingMinutes,
                                  (long)item.remainingSeconds];
    
    return cell;
}

// 记得在ViewController销毁时停止Timer
- (void)dealloc {
    [self.countdownTimer invalidate];
}

关键改进点说明

  • 每个倒计时状态都存在独立的CountdownItem模型里,不会互相干扰。
  • 只用一个全局Timer,每秒统一更新所有模型的剩余时间,避免多个Timer导致的性能问题和逻辑混乱。
  • 自动判断每个倒计时是否结束,所有倒计时完成后自动停止Timer。
  • Cell配置时直接从对应模型取数据,逻辑清晰,不会出现复用问题。

内容的提问来源于stack exchange,提问作者shiwani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:10:32