Search code examples
iosobjective-cuitableviewuislider

UISlider in Dynamic UITableView


I am creating an app in where I need to add a bunch of sliders in a Dynamic UITableView. I added the slider like this:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    UISlider *slider = [[UISlider alloc]init];
    //ALL OTHER CODE
    [cell addSubview:slider];
    return cell;
}

Now the slider is added to the UITableView but the if I changed the value of the first slider another slider changes with it.I know this is something to do with dequeing the cell but how do I fix it?

EDIT:

I tried @daveMack answer like this:

CustomCell.m:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
        self.checkBox = [[M13Checkbox alloc]initWithTitle:@"Checkbox!"];
        self.checkBox.checkAlignment = M13CheckboxAlignmentLeft;
        [self addSubview:self.checkBox];
    }
    return self;
}

Cell For Row At Index Path:

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

    cell = [self.tableView dequeueReusableCellWithIdentifier:@""];
    if (!cell) {
        cell = [[CheckboxCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
        return cell;
    }
    return cell;
}

Solution

  • No, no, no! I would not suggest you add views like that to your UITableViewCell. Funky stuff can happen as you have experienced yourself because of the dequeueing process.

    I suggest you do the following:

    1. Create a custom table view cell with its appropriate .h, .m file and .xib file
    2. In your custom cell you can add WHATEVER views you like and however many views that you like.
    3. Make sure you create a property of type UIScrollView in your .h file and link it to the interface builder to your custom cell's slider, call the property slider.
    4. Now in your main view controller where you are creating your table, make sure you have an NSMutableArray and name it something like sliderValuesArray that can store all your slider values for each cell. You want to make sure that the number of cells is equal to the number of elements in your sliderValuesArray.
    5. Then you can do something like this in your cellForRowAtIndexPath delegate method:

    In your cellForRowAtIndexPath method do something like this:

    myCustomCell.slider.maximumValue = 100;
    myCustomCell.slider.minimumValue = 1;
    myCustomCell.slider.continuous = TRUE;
    //set a method which will get called when a slider in a cell changes value
    [myCustomCell.slider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
    
    //Keep a reference to each slider by assigning a tag so that we can determine 
    //which slider is being changed
    myCustomCell.slider.tag = indexPath.row;
    
    //Grab the value from the sliderValuesArray and set the slider knob to that position
    myCustomCell.slider.value = [[sliderValuesArray objectAtIndex:indexPath.row] intValue];
    

    Now in your sliderChanged method you can do this:

    -(void)sliderChanged:(UISlider)sender{
        //Grab the slider value, it needs to be converted to an NSNumber so that we can
        //store it successfully as an object in our sliderValuesArray
        NSNumber sliderValue = [NSNumber numberWithInt:sender.value];
        //This is how we determine which position in our slidersArray we want to update,
        //Based on the tag we set our slider view on initialisation in our cellForRowAtIndexPath
        int cellPosition = sender.tag;
    
        //Use the cellPosition to update the correct number in our sliderValuesArray
        //with the sliderValue retrieved from the slider that the user is sliding
        [sliderValuesArray replaceObjectAtIndex:cellPosition withObject:sliderValue];
    }