tableView滚动时,tableViewCells中的运行计时器被覆盖 [英] running timers in tableViewCells being overwritten when tableView scrolls

查看:89
本文介绍了tableView滚动时,tableViewCells中的运行计时器被覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾多次尝试过这个问题,但我无法解释发生了什么。也许一些屏幕截图可能有帮助。我只能发一个,因为我还没有足够的声望点。

I have tried asking this question several times but I haven't been able to explain what is going on. Maybe some screen shots may help. I can only post one because I don't have enough reputation points yet.

桌面视图滚动后的屏幕截图

您可以看到其中一个计时器(2)已被重置。我试图修复这种方法但没有成功。以下是将计时器放入tableview单元格的代码:

You can see that one of the timers (2) has been reset. I have tried to fix this multiple ways without success. Here is the code that puts the timers into the tableview cells:

    -(void) calculateTimer:(NSTimer *)theTimer
{
    self.timerItem = [theTimer userInfo];
        // for date only cell
        if(self.timerItem.timerType == 0){
            [theTimer invalidate];
        }

    for (NRCItemCell *cell in [self.tableView visibleCells])
{
    NSIndexPath *ip = [self.tableView indexPathForCell:cell];
    NSUInteger row = [[[NRCItemStore sharedStore]allItems] indexOfObjectIdenticalTo:self.timerItem];
    if (row == ip.row){

            [self configureTimers:cell forRowAtIndexPath:ip];
            cell.timer.text = self.timerItem.timerOutput;
            cell.timerName.text = self.timerItem.timerName;
        }
}
}


-(void)configureTimers:(NRCItemCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

    NRCtimerItem *item = [[NRCItemStore sharedStore]allItems][indexPath.row];
    NSInteger timerType = item.timerType;


    // timerType set by TimerTypeTableView Controller as follows:

    // 0 - date
    // 1 - seconds elapsed
    // 2 - minutes elapsed
    // 3 - hours elapsed
    // 4 - days elapsed
    // 5 - months elapsed
    // 6 - years elapsed

    switch (timerType) {
        case 0:{
            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
            [dateFormatter setTimeStyle:NSDateFormatterNoStyle];

            NSDate *date = [NSDate date];
            NSString *formattedDateString = [dateFormatter stringFromDate:date];
            item.timerOutput = formattedDateString;
        }
            break;
        case 1:
        {
            NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
            interval = (-1 * interval);
            int time = round(interval);
            div_t h = div(time, 3600); //seconds total, divided by 3600 equals
            int hours = h.quot;         // hours, divided by 60 equals
            div_t m = div(h.rem, 60);   // minutes
            int minutes = m.quot;
            int seconds = m.rem;        // and remainder is seconds
            //  NSLog(@"%d:%d:%d", hours, minutes, seconds);
            //NSString *intervalString = [NSString stringWithFormat:@"%ld", (long)time];
            NSString *intervalString = [NSString stringWithFormat:@"%d hours, %d minutes, %d seconds", hours, minutes, seconds];

            NSString *outputString = [intervalString stringByAppendingString:@" ago"];
            item.timerOutput = outputString;

        }
            break;
        case 2:
        {
            NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
            interval = (-1 * interval);
            int time = roundf(interval);
            div_t h = div(time, 3600);      // seconds total, divided by 3600 equals
            int hours = h.quot;             // hours, divided by 60 equals
            div_t m = div(h.rem, 60);       // minutes
            int minutes = m.quot;
            NSString *intervalString = [NSString stringWithFormat:@"%d hours, %d minutes", hours, minutes];
            NSString *outputString = [intervalString stringByAppendingString:@" ago"];

            item.timerOutput = outputString;

        }
            break;
        case 3:
        {
            NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
            interval = (-1 * interval);
            int time = roundf(interval);
            div_t h = div(time, 3600); // seconds total, divided by 3600 equals
            int hours = h.quot;        // hours
            NSString *intervalString = [NSString stringWithFormat:@"%d hours", hours];
            NSString *outputString = [intervalString stringByAppendingString:@" ago"];

            item.timerOutput = outputString;
        }
            break;
        case 4:
        {
            NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
            interval = (-1 * interval);
            int time = roundf(interval);
            div_t h = div(time, 3600); // seconds total, divided by 3600 equals
            int hours = h.quot;        // hours, divided by 24 equals
            div_t d =div(h.rem, 24);   // days
            int days = d.quot;
            NSString *intervalString = [NSString stringWithFormat:@"%d days, %d hours", days, hours];
            NSString *outputString = [intervalString stringByAppendingString:@" ago"];

            item.timerOutput = outputString;
        }
            break;
        case 5:
        {
            NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
            interval = (-1 * interval);
            int time = roundf(interval);
            div_t h = div(time, 3600); // seconds total, divided by 3600 equals
            __unused int hours = h.quot;        // hours, divided by 24 equals
            div_t d =div(h.rem, 24);   // days
            int days = d.quot;
            div_t y = div(d.rem, 12);// divided by 12 equals months
            int months = y.quot;
            NSString *intervalString = [NSString stringWithFormat:@"%d months, %d days", months, days];
            NSString *outputString = [intervalString stringByAppendingString:@" ago"];
            item.timerOutput = outputString;
        }
            break;
        case 6:
        {
            NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
            interval = (-1 * interval);
            int time = roundf(interval);
            div_t h = div(time, 3600); // seconds total, divided by 3600 equals
            __unused int hours = h.quot;        // hours, divided by 24 equals
            div_t d =div(h.rem, 24);   // days
            int days = d.quot;
            div_t y = div(d.rem, 365);// divided by 365 equals years
            int years = y.quot;
            NSString *intervalString = [NSString stringWithFormat:@"%d years, %d days", years, days];
            NSString *outputString = [intervalString stringByAppendingString:@" ago"];
            item.timerOutput = outputString;
        }
            break;
    }
}

关键是for(NRCItemCell *单元格在[ self.tableView visibleCells])快速枚举。我们的想法是遍历可见单元格,并且只有在单元格的indexPath等于我的数据存储区中的计时器位置时才更新单元格。但是,看起来滚动tableView会导致indexPath与数据存储区中定时器的位置不匹配,从而导致错误的单元被覆盖。我已经搜索了所有的答案,并尝试了几种不同的方法,但解决方案取决于我的自定义单元格中的字幕标签没有被覆盖,除非单元格位置与数据存储位置匹配(这是MVC应该工作的方式,据我所知)。但是使用可重复使用的单元格和滚动显然不能像我想象的那样工作。如果有解决方案,我肯定会得到帮助。提前致谢!

The key is the for(NRCItemCell *cell in [self.tableView visibleCells]) fast enumeration. The idea is to loop through the visible cells and only update a cell if the cell's indexPath is equal to the position of the timer in my datastore. However, it looks like scrolling the tableView causes a mismatch between indexPath and and position of the timer in the datastore so that the wrong cell gets overwritten. I have searched all over for an answer and have tried several different approaches but the solution depends on the subtitle label in my custom cell not being overwritten unless the cell position matches the datastore position (which is the way MVC should work, as I understand it). But using reusable cells and scrolling apparently doesn't work the way I thought it did. If there is a solution, I sure would like the help. Thanks in advance!

推荐答案

我的不好。我在代码中发现了这个错误。它根本不是tableView。我正确地将计时器存储在数组中,而不是存储在单元格中,即使这是代码中的注释所说的。错误是我无意中每次通过tableView时都会触发一个计时器,因此这些计时器会在不可预测的时间触发,然后我的代码将覆盖相应计时器的单元格。很多调试工作,但很好的经验。代码现在正在运作。

My bad. I found the bug in my code. It wasn't with tableView at all. I was storing the timers in an array, correctly, not in the cell, even though that's what the comments in the code said. The bug was that I was inadvertently firing a timer every pass through the tableView, so these timers would fire at unpredictable times and then my code would overlay the cell for the corresponding timer. A lot of debugging work, but good experience. Code is working now.

感谢您的评论!

这篇关于tableView滚动时,tableViewCells中的运行计时器被覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆