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.
screenshot after tableview scroll
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;
}
}
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!