doe doe - 1 month ago 9
iOS Question

Wrong indexPath.row number on reusable cells in TableView

As you can see in the code below I have a

tableView
for times of racers. First racer(s) have gold circle (
goldMedal
image) second(s) have silver and third(s) bronze, everyone else has only
medal
image. Theese images are simply gold/silver/bronze/black circles. I want to put an
UILabel
view on this medal image with number that will decribe raecer's order in the race, so racers with best (same) times will have
goldMedal
image with number 1 on it, second racer(s) will have
silverMedal
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
helpIndex
variable to count numbers for racers that are 4. or worse, but now there is
indexPath.row
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];
helpIndex++;
if (indexPath.row < golds) {
sksTableViewCell.imageView.image = [UIImage imageNamed:@"goldMedal"];
numberLabel.text = @"1";
helpIndex--;
} else if (indexPath.row < (golds+silvers)) {
sksTableViewCell.imageView.image = [UIImage imageNamed:@"silverMedal"];
numberLabel.text = @"2";
helpIndex--;
} else if (indexPath.row < (golds+silvers+bronzes)) {
sksTableViewCell.imageView.image = [UIImage imageNamed:@"bronzeMedal"];
numberLabel.text = @"3";
helpIndex--;
}
[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
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.
Comments