Updating UITableView every second

I am wondering what is the correct way to show the countdown in rather complex UITableViewCells, each cell has one countdown with a different time.

I could have an NSTimer for each cell separately, but then the cells won't update at the same time. I can have one NSTimer for all cells, but calling reloadData on uitableview is quite expensive to do every second, isn't it?

Obviously, only visible cells need to be updated.

Any ideas, best practice, know how about this?

+3


source to share


4 answers


Some thoughts on how I would implement this:



  • Create your own cell prototype class and implement the method update

    in that class. This method updates the label.
  • Create a timer in your custom class TableViewController

  • Whenever the timer fires, iterate through the cells through indexPath

    . UITableView.CellForRowAtIndexPath

    returns nil

    for cells that are not visible.
  • Call the cell method update

    for each of these visible cells.
+6


source


An alternative approach would be to use NSNotificationCenter

.

  • Your view controller will send a notification when your time period expires.

  • Each of your UITableViewCells registers for this notification and updates its display in response.



Note that in order to prevent memory leaks, you need to remove each UITableViewCell as an observer as it goes off-screen. It's easy to do in UITableViewDelegate

tableView:didEndDisplayingCell:forRowAtIndexPath:

.

The advantage of this is that you don't have to subclass the UITableViewCell and try to keep track of every cell that needs updating.

+2


source


In cellForRowAtIndexPath, store a reference to every cell you need.

if (indexPath.row == indexPath1.row) {
    _timerCell1 = cell;
} else if (indexPath.row == indexPath2.row) {
    _timerCell2 = cell;
} ...

      

Schedule a timer to update each cell when that cell needs to be updated.

_timer1 = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateCell1) userInfo:nil repeats:true];
_timer2 = [NSTimer timerWithTimeInterval:0.25 target:self selector:@selector(updateCell2) userInfo:nil repeats:true];

      

This removes the need for any updates to the tableView.

0


source


From the image, it looks like your model is a set of actions the user plans to take. I would arrange things this way:

1) MyAction is an NSObject with a name and a due date. MyAction implements something like this:

- (NSString *)timeRemainingString {
    NSDate *now = [NSDate date];
    NSTimeInterval secondsLeft = [self.dueDate timeIntervalSinceDate:now];
    // divide by 60, 3600, etc to make a pretty string with colons
    // just to get things going, for now, do something simple
    NSString *answer = [NSString stringWithFormat:@"seconds left = %f", secondsLeft];
    return answer;
}
2) StatusViewController keeps a handle to the model which is an NSArray of MyActions, it also has an NSTimer (just one) that tells it time is passing.

// schedule timer on viewDidAppear
// invalidate on viewWillDisappear

- (void)timerFired:(NSTimer *)timer {
    [self.tableView reloadData];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.model.count;
}


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

    MyAction *myAction = [self.model objectAtIndex:indexPath.row];

    // this can be a custom cell.  to get it working at first,
    // maybe start with the default properties of a UITableViewCell

    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    cell.textLabel.text = [myAction timeRemainingString];
    cell.detailTextLabel.text = [myAction name];
}

      

-1


source







All Articles