【问题标题】:Display StopWatch Timer in UITableViewCell dynamically在 UITableViewCell 中动态显示秒表计时器
【发布时间】:2013-06-17 12:12:55
【问题描述】:

我想保留计时器值并从新的UITableViewCell 开始显示它,但我的问题是我能够成功地在第一个单元格上显示秒表计时器但是当我尝试在UITableView 中添加一个新单元格时我的计时器设置为第二个单元格,我无法定义如何让我的第一个计时器保持活动状态。

我想管理一个数组,但我想每次都调用 reload TableData,但我认为这很糟糕:(

我尝试了如下解决方法,但我不知道如何在前一个单元格上显示 timerValue,使用相同计数的工作秒表动态和从开始的新单元格 timerValue。

一个静态解决方案,但我的行动态插入并从 TableView 中删除,因此静态解决方案限制了我的特定行数,并寻找动态解决方案。

    - (void) putDelayOnTimeOut {


            if (!_timerQueue) {
                _timerQueue = dispatch_queue_create("timer_queue", NULL);
            }
            dispatch_async(_timerQueue, ^{

                self.startTime = [NSDate date];

                if (globalRowIndex == 0) {

                    _timer = [NSTimer scheduledTimerWithTimeInterval:0.6 target:self selector:@selector(showTimeoutActivity:) userInfo:nil repeats:YES];
                } else if (globalRowIndex == 1) {
                    _timer = [NSTimer scheduledTimerWithTimeInterval:0.6 target:self selector:@selector(showTimeoutActivity1:) userInfo:nil repeats:YES];
                }

                //[[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
                [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];

                //[[NSRunLoop currentRunLoop] run];
                [_timer fire];
            });

    }


    - (void)showTimeoutActivity:(id)unused
    {
        if( [_timer isValid] )
        {
            NSTimeInterval interval = [self.startTime timeIntervalSinceNow];
            interval = (-1 * interval);

            NSString *timerString = [self formatInterval:interval];
            NSLog(@"%@", timerString);

            MyCell *cell = (MyCell *)[self.activeCallTbl viewWithTag:globalRowIndex+10];
            //NSIndexPath *indexPath = [self.activeCallTbl indexPathForCell:cell];
            //NSLog(@"%d",indexPath.row);
            cell.timerLbl.text = timerString;

        }
    }


 - (void)showTimeoutActivity1:(id)unused
    {
        if( [_timer isValid] )
        {
            NSTimeInterval interval = [self.startTime timeIntervalSinceNow];
            interval = (-1 * interval);


            NSString *timerString = [self formatInterval:interval];
            NSLog(@"%@", timerString);

            MyCell *cell = (MyCell *)[self.activeCallTbl viewWithTag:globalRowIndex+10];
            //NSIndexPath *indexPath = [self.activeCallTbl indexPathForCell:cell];
            //NSLog(@"%d",indexPath.row);
            cell.timerLbl.text = timerString;

        }
    }

【问题讨论】:

  • 您设置标签 iphone 和 ios 以便每个人都能看到您的问题

标签: iphone ios objective-c xcode4.5 nstimer


【解决方案1】:

我不确定是否完全理解您的要求……但我会尝试。

一个简单的解决方案是继承 UITableViewCell 并将计时器添加到单元格本身。因此单元格将具有对计时器的引用,并且每次将新单元格添加到 TableView 时都会创建一个新单元格

附上示例代码:Link(我已经静态添加了 3 个单元格,但您可以根据需要添加,只需点击一个单元格即可启动计时器,如果再次点击,计时器将从 0 重新开始)

创建您的自定义单元子类并添加一些方法,如下所示:

- (void) startTimer
{

    // invalidate a previous timer in case of reuse
    if (self.timer)
        [self.timer invalidate];


    self.startTime = [NSDate date];

    // create a new timer
    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.6 target:self selector:@selector(calculateTimer) userInfo:nil repeats:YES];

    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

    [self.timer fire];
}

- (void)calculateTimer
{
    NSTimeInterval interval = [self.startTime timeIntervalSinceNow];
    interval = (-1 * interval);

    NSString *intervalString = [NSString stringWithFormat:@"%f", interval];

    self.timerLabel.text = intervalString;
}

然后,在 UITableViewController 实现中,只需调用

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    TimerCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
    [cell startTimer];
}

更多详情请咨询或查看附件项目。

这是我找到的最快的方法,尽管有人更愿意将计时器代码和引用留在 Table View Controller 中(但您需要更多代码)

编辑

正如 Spynet 在评论中所写,如果您有超过 7/8 个单元格(可以适合屏幕的单元格数量),这将不起作用,因为当您滚动 UITableView 单元格时会重复使用。因此单个单元格将在不同的 indexPaths 中使用,因此在第一个单元格上启动一个计时器,然后滚动,将导致您看到计时器已经每 7/8 个单元格启动(因为它是之前创建的单元格的计时器)

解决这个问题有很多方法。一种方法是从单元格中删除计时器并在 ViewController 中创建一个计时器数组。每个索引路径一个计时器。 另一种方法(但如果单元格很多,我不推荐它)是不要重复使用单元格。

从我的示例项目开始:
1 -创建一个 nib 文件(称为 TimerCell.xib)并从情节提要中复制/粘贴其中的单元原型
2 -将此属性添加到TimerViewController

@interface TimerViewController ()
@property (strong, nonatomic) NSMutableArray *cells;
@end

3 -initWithCoder方法中初始化数组:

- (id)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        _cells = [NSMutableArray array];
    }
    return self;
}

4 - 更新cellForRowAtIndexPath 方法并将其更改为:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    TimerCell *cell = nil;

    if ([self.cells count] > indexPath.row)
    {
        cell = [self.cells objectAtIndex:indexPath.row];
    } else {
        cell = [[[NSBundle mainBundle] loadNibNamed:@"TimerCell" owner:self options:nil] objectAtIndex:0];
        [self.cells addObject:cell];
    }

    // Configure the cell...

    return cell;
}

这样细胞就不会被重复使用

【讨论】:

  • 您或多或少地回答了我的问题,我已根据您的提示对其进行了相应修改,我的主要问题是访问 cell.timerlbl 出 TableView 委托并使用计时器保持值并且不要暂停,并且从您的解决方案中,问题已得到解决,所有 cell.timerlbl 工作正常。谢谢。
  • 你能再建议我一件事,我已经在 UITableViewCell 类中实现了我的计时器,它工作正常,但我可以知道如何在 UITableView 的 Main 类上存在的标签上显示相同的值存在。我的 UILabel 在 UITableview 类之外,想在超类的 UILabel 上打印相同的计时器值
  • 您可以在自定义单元格上添加委托属性,并在每次触发计时器时提醒委托。但是,当您有 2-3 或 4 个计时器但其他类中只有一个标签时该怎么办?
  • @LombaX 很抱歉这么说,你的代码也有我现在面临的同样的错误。您只需将表格行增加到 30 并点击单元格并滚动并查看代码中发生的情况,如果您有任何想法或修复请与我分享
  • 如果您有大量单元格,这是正常的,默认情况下会重用 UITableViewController 中的单元格。您可以通过多种方式解决。示例 1:从单元格中删除计时器并使用视图控制器中的数组来引用所有计时器,每个 indexpath.row 一个。示例 2:不要重复使用单元格(如果由于内存原因有很多单元格,则不好)。我解释例子2编辑帖子
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-04
相关资源
最近更新 更多