doe doe - 1 year ago 80
iOS Question

Wrong indexPath.row number on reusable cells in TableView

As you can see in the code below I have a

for times of racers. First racer(s) have gold circle (
image) second(s) have silver and third(s) bronze, everyone else has only
image. Theese images are simply gold/silver/bronze/black circles. I want to put an
view on this medal image with number that will decribe raecer's order in the race, so racers with best (same) times will have
image with number 1 on it, second racer(s) will have
image with number 2 on it and so on. The problem is that when I have too many racers in tableview and I scroll down, racers don't have the same numbers. That numbers are changing when scrolling. I don't know what to do with that. Can anyone help me?

Also I used
variable to count numbers for racers that are 4. or worse, but now there is
and none of theese 2 ways worked. Can anyone give me at least his point of view how he would solve this problem? Thanks

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"SKSTableViewCell";
SKSTableViewCell *sksTableViewCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

UILabel *numberLabel = [[UILabel alloc] initWithFrame:CGRectMake(sksTableViewCell.frame.origin.x+22.5, sksTableViewCell.frame.origin.y+20.5, 15, 15)];
numberLabel.font = [UIFont systemFontOfSize:12];
numberLabel.textColor = [UIColor whiteColor];
numberLabel.textAlignment = NSTextAlignmentCenter;
numberLabel.adjustsFontSizeToFitWidth = YES;

if (!sksTableViewCell) {
sksTableViewCell = [[SKSTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
sksTableViewCell.backgroundColor = [UIColor clearColor];
if ([[[[ArraySingleton sharedManager].sharedArray objectAtIndex:indexPath.row] times] count]) {
sksTableViewCell.expandable = YES;
} else {
sksTableViewCell.expandable = NO;

sksTableViewCell.imageView.image = [UIImage imageNamed:@"medal"];

// Medals
int golds = [[self.bestThreeRacersDictionary objectForKey:@"golds"] intValue];
int silvers = [[self.bestThreeRacersDictionary objectForKey:@"silvers"] intValue];
int bronzes = [[self.bestThreeRacersDictionary objectForKey:@"bronzes"] intValue];

sksTableViewCell.textLabel.text = [NSString stringWithFormat:@" %@",[[[ArraySingleton sharedManager].sharedArray objectAtIndex:indexPath.row] name]];
numberLabel.text = [NSString stringWithFormat:@"%lu", [Racer shift:golds silvers:silvers bronzes:bronzes]+indexPath.row];
if (indexPath.row < golds) {
sksTableViewCell.imageView.image = [UIImage imageNamed:@"goldMedal"];
numberLabel.text = @"1";
} else if (indexPath.row < (golds+silvers)) {
sksTableViewCell.imageView.image = [UIImage imageNamed:@"silverMedal"];
numberLabel.text = @"2";
} else if (indexPath.row < (golds+silvers+bronzes)) {
sksTableViewCell.imageView.image = [UIImage imageNamed:@"bronzeMedal"];
numberLabel.text = @"3";
[sksTableViewCell addSubview:numberLabel];

if ([[[[ArraySingleton sharedManager].sharedArray objectAtIndex:indexPath.row] times] count]) {
sksTableViewCell.expandable = YES;
} else {
sksTableViewCell.expandable = NO;
sksTableViewCell.textLabel.text = [NSString stringWithFormat:@"%@", [[[ArraySingleton sharedManager].sharedArray objectAtIndex:indexPath.row] name]];

return sksTableViewCell;

Answer Source
sksTableViewCell = [[SKSTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

You should pass your CellIdentifier here otherwise there is no point of checking cell exist or not. UITableView will always create new cell.

My couple of notes which might help you:

  1. If you prefer, you can use different reusable identifiers parameter and based on identifier distinguish cells inside cell definition.

    -(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier  
  2. You can create four different classes each subclass of table cell for Gold, Silver, Bronze and black and define everything in them and simply call them based on requirement. That will reduce your overhead as you wont be doing this work over and over again while scrolling up and down. Plus in future if you need to do more specific work for each cell it will be very convenient for you.

  3. Last thing having if else ladder is not good as well. Code can go out of proportion very soon this way and reduces readability a lot.
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download