Search code examples
iosobjective-cuitableviewuistepper

Updating UITableViewCell contents with UIStepper


I have a table view with multiple sections, and custom table view cells. I'm trying to put a stepper in my cells, and a label to indicate the stepper value. I have added an IBAction for the UIStepper within the cell in my view controller (I figured that the view controller should handle this event instead of the cell):

- (IBAction)mealAmountStepperChanged:(id)sender
{
    // Get the cell in which the button was pressed
    SOMealTableViewCell *cell = (SOMealTableViewCell *)[[sender superview] superview];
    // Get the value of the stepper (it has an outlet in my custom cell
    int value = cell.mealAmountStepper.value;
    // Update the text field of the cell with the new value (also has an outlet in the custom cell)
    cell.mealAmountField.text = [NSString stringWithFormat:@"%d",value];
}

The problem is that this method updates the corresponding field in all the sections, not just the one I want. How can I manage to change the text in only one cell?

Update:

I have added an "amount" property to my Meal class (which provides the data for the table view cells) and mofidied the mealAmountStepperChanged: method:

- (IBAction)mealAmountStepperChanged:(id)sender
{
    // Get the cell in which the button was pressed
    SOMealTableViewCell *cell = (SOMealTableViewCell *)[[sender superview] superview];
    // Get the value of the stepper (it has an outlet in my custom cell
    int value = cell.mealAmountStepper.value;
    // Get the indexpath of the cell in which the stepper was pressed
    NSIndexPath *indexPath = [self.menuTableView indexPathForCell:cell];

    SOMealManager *manager = [SOMealManager sharedMealManager];
    SOMeal *currentMeal;
    switch (indexPath.section)
    {
        case 0:
            currentMeal = manager.startersArray[indexPath.row];
            break;
        case 1:
            currentMeal = manager.soupsArray[indexPath.row];
            break;
        case 2:
            currentMeal = manager.mainDishesArray[indexPath.row];
            break;
        case 3:
            currentMeal = manager.dessertsArray[indexPath.row];
            break;
        case 4:
            currentMeal = manager.drinksArray[indexPath.row];
            break;
        case 5:
            currentMeal = manager.alcoholicDrinksArray[indexPath.row];
            break;
        default:
            break;
    }

    currentMeal.amount = value;
    dispatch_async(dispatch_get_main_queue(), ^
    {
        [self.menuTableView reloadData];
    });

}

Now the action only updates one row at a time but it seems that the stepper value remains the same for all sections (so when I update a cell in another section, it won't start at 0, but at the value it was changed to in the other previous section).

Final update

The previous problem can be solved if I add the cellForRowAtIndexPath: table view datasource method:

cell.mealAmountStepper.value = currentMeal.amount;

It sets the stepper's value to the Meal object's amount property so it will change properly.


Solution

  • It changes in all the section because all cells have a mealAmountField, and you told them to set their text to the value of your stepper. To fix this, you need a "field" in your data source to keep track of the values in the label. Depending on what your data source for your cells looks like now, this "field" could be a key-value pair in a dictionary, with your data source being an array of dictionaries. In your stepper's action method, you would get the indexPath of the cell the stepper is in, and use that value to update the correct entry in your array of dictionaries. This is the way table views always work -- they are for displaying values, not for storing them.