doe doe - 1 month ago 9
Objective-C Question

indexPath.row gives weird values

I have a custom cell. In

cellForRowAtIndexPath
method I am displaying
indexPath.row
number as custom
UILabel
also defined in
cellForRowAtIndexPath
. That label is added as a subview of that custom cell. When I have lots of cells and swipe down the tableview, that
indexPath.row
numbers have weird values and if I scroll more, values are hgher. How can I bypass this?

[EDIT] my code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"SKSTableViewCell";

self.sksTableViewCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (!self.sksTableViewCell)
self.sksTableViewCell = [[SKSTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

self.sksTableViewCell.textLabel.text = [NSString stringWithFormat:@" %@",[[[ArraySingleton sharedManager].sharedArray objectAtIndex:indexPath.row] name]];
self.sksTableViewCell.backgroundColor = [UIColor clearColor];

if ([[[[ArraySingleton sharedManager].sharedArray objectAtIndex:indexPath.row] times] count]) {
self.sksTableViewCell.expandable = YES;
} else {
self.sksTableViewCell.expandable = NO;
}

// UIButton for directly switching racers
UIButton *stopwatchIcon = [UIButton buttonWithType:UIButtonTypeCustom];
[stopwatchIcon addTarget:self action:@selector(pressedButtonToGoToTheRacerDirectly:) forControlEvents:UIControlEventTouchUpInside];
UIImage *img = [UIImage imageNamed:@"stopwatch"];
stopwatchIcon.frame = CGRectMake(self.view.bounds.size.width-70, 27.5-img.size.height/2, img.size.width, img.size.height);
[stopwatchIcon setImage:img forState:UIControlStateNormal];
stopwatchIcon.tag = [[self.indexDictionary valueForKey:[NSString stringWithFormat:@"%@", [[[ArraySingleton sharedManager].sharedArray objectAtIndex:indexPath.row] name]]] intValue];
[self.sksTableViewCell addSubview:stopwatchIcon];

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

// Medal image and view
UIImage *medalImage = [UIImage imageNamed:@"medal"];
UIImageView *medalImageView = [[UIImageView alloc] initWithFrame:CGRectMake(stopwatchIcon.frame.origin.x-medalImage.size.width-7.5, 27.5-medalImage.size.height/2, medalImage.size.width, medalImage.size.height)];
// TextLabel
UILabel *numberLabel = [[UILabel alloc] initWithFrame:CGRectMake(medalImageView.frame.origin.x+medalImageView.frame.size.width/4, medalImageView.frame.origin.y+medalImageView.frame.size.height/4, medalImageView.frame.size.width/2, medalImageView.frame.size.height/2)];
numberLabel.backgroundColor = [UIColor clearColor];
numberLabel.textColor = [UIColor whiteColor];
numberLabel.textAlignment = NSTextAlignmentCenter;
numberLabel.adjustsFontSizeToFitWidth = YES;
numberLabel.font = [UIFont systemFontOfSize:12];
numberLabel.text = [NSString stringWithFormat:@"%i", [Racer shift:golds silvers:silvers bronzes:bronzes]+helpIndex];
helpIndex++;
if (indexPath.row < golds) {
medalImage = [UIImage imageNamed:@"goldMedal"];
numberLabel.text = @"1";
helpIndex--;
} else if (indexPath.row < (golds+silvers)) {
medalImage = [UIImage imageNamed:@"silverMedal"];
numberLabel.text = @"2";
helpIndex--;
} else if (indexPath.row < (golds+silvers+bronzes)) {
medalImage = [UIImage imageNamed:@"bronzeMedal"];
numberLabel.text = @"3";
helpIndex--;
}
medalImageView.image = medalImage;
medalImageView.tag = 5;
numberLabel.tag = 5;
[self.sksTableViewCell addSubview:medalImageView];
[self.sksTableViewCell addSubview:numberLabel];

return self.sksTableViewCell;
}

Answer

Avoid creating new UIButtons and UILabels in cellForRow methods. Cells in UITableView are reused, so the objects which disappear from the screen when you scroll are used again to show new rows. And you're adding a new view every time this happens.

Instead you should create all view hierarchy just once and update the views you need to be updated.

if (!cell) {
    cell = [[SKSTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    //create all your subviews here
}

//update subviews here