Swift - Increment Label With Stepper in Tableview Cell

Swift - Increment Label with Stepper in TableView Cell

Easiest solution (simplyfied):

  • Create a model BuyStat with a property purchaseAmount (it's crucial to be a class).

    You are strongly discouraged from using multiple arrays as data source

    class BuyStat {

    var purchaseAmount = 0.0

    init(purchaseAmount : Double) {
    self.purchaseAmount = purchaseAmount
    }
    }
  • In the view controller create a data source array

    var stats = [BuyStat]()
  • In viewDidLoad create a few instances and reload the table view

    stats = [BuyStat(purchaseAmount: 12.0), BuyStat(purchaseAmount: 20.0)]
    tableView.reloadData()
  • In the custom cell create a property buyStat to hold the current data source item with an observer to update stepper and label when buyStat is set

    class BuyStatsCell: UITableViewCell {

    @IBOutlet weak var purchaseAmount: UILabel!
    @IBOutlet weak var addSubtract: UIStepper!

    var buyStat : BuyStat! {
    didSet {
    addSubtract.value = buyStat.purchaseAmount
    purchaseAmount.text = String(buyStat.purchaseAmount)
    }
    }

    @IBAction func stepperAction(_ sender: UIStepper) {
    buyStat.purchaseAmount = sender.value
    self.purchaseAmount.text = String(sender.value)
    }
    }
  • In cellForRowAtIndexPath get the data source item and pass it to the cell

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "BuyStatsTabCell", for: indexPath) as! BuyStatsCell
    cell.buyStat = stats[indexPath.row]
    return cell
    }

The magic is: When you are tapping the stepper the label as well as the data source array will be updated. So even after scrolling the cell will get always the actual data.

With this way you don't need protocols or callback closures. It's only important that the model is a class to have reference type semantics.

Updating label in UITableViewCell with UIStepper in Swift

Initially FoodTableViewCell is the ONLY target for UIStepper value changed (looking at @IBAction inside FoodTableViewCell).

When you dequeue a cell to display on screen, you call -

cell.stepper.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged)

which causes your ShoppingListVC instance to be added as an additional target every time a cellForRow call is executed.

Things to fix :

  1. Remove all of your NotificationCenter related code from both classes.
  2. Remove cell.stepper.addTarget() line as well.

This would give you a better idea of why it is happening this way. Update your question with these changes in case you still don't have what you want.



UPDATE

// Inside cellForRow
cell.stepper.value = food.serving

Stepper on tableview cell (swift)

As mentioned by @A-Live, your component is being reused and so need to be updated.

So in your view controller:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "reviewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ReviewTableViewCell


var imageView: UIImageView?
let photoG = self.photos[indexPath.row]
imageView = cell.contentView.viewWithTag(1) as? UIImageView
//let layout = cell.goodiesImage
let tag = indexPath.row // +1
cell.tag = tag
photoG.fetchImageWithSize(CGSize(width: 1000, height: 1000), completeBlock: { image, info in
if cell.tag == tag {
imageView?.image = image
cell.goodiesImage.image = image
}
})
cell.countStepper.value = XXX[indexPath.row].value; //Here you update your view
cell.stepperLabel.text = "x \(Int(cell.countStepper.value))" //And here

And

func stepperButton(sender: ReviewTableViewCell) {
if let indexPath = tableView.indexPathForCell(sender){
print(indexPath)
XXX[sender.tag].value = sender.counterStepper.value //Here you save your updated value
}

Swift - Stepper in TableViewCell - Action not Responding

You've disabled the user interaction in your cell for row at index method:

cell.isUserInteractionEnabled = false;

You should remove this line.

Swift Delegation - Use Stepper in Tableview Cell to Update Label in Separate Class

If you are using a dynamic UITableView, you might try the following inside your cellForRowAtIndexPath:

  1. When you init your cell with dequeueCellWithReuseIdentifier, cast it as a BuyStatsCell (maybe with as! BuyStatsCell) to get access to its class variables.
  2. Set up the delegation with cell.setRemaining = self. The use of self assumes that your tableView's cellForRowAtIndexPath is inside the BuyStats viewController class. If it's not, you would want to get the reference for your BuyStats object in the class where your tableView's code lives, and use that reference in place of self, like cell.setRemaining = /*yourBuyStatsObjectReferenceGoesHere*/.

Hope that helps.



Related Topics



Leave a reply



Submit