Swift - Increment Label with Stepper in TableView Cell

老子叫甜甜 提交于 2019-11-26 16:38:32

问题


Another Swift beginner here. I simply want a Stepper in each of my TableView cells that increments a label in the same cell.

I have found a couple of questions on this topic, but they include other elements and I haven't been able to extract the basic concept.

Swift Stepper Action that changes UITextField and UILabel within same cell

Stepper on tableview cell (swift)

So far I have connected IBOutlets for my Label and Stepper, as well as an IBAction for my Stepper in my cell class.

class BuyStatsCell: UITableViewCell{

    //these are working fine

    @IBOutlet weak var category: UILabel!
    @IBOutlet weak var average: UILabel!
    @IBOutlet weak var price: UILabel!


    //Outlet for Label and Stepper - How do I make these work?

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

    //Action for Stepper - And this?

    @IBAction func stepperAction(_ sender: UIStepper) {
        self.purchaseAmount.text = Int(sender.value).description

    }

}

And I understand the concept of reusing the cell in the cellForRowAt indexPath

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "BuyStatsTabCell", for: indexPath) as! BuyStatsCell

        cell.isUserInteractionEnabled = false

 //these are working 

        cell.category.text = categories[indexPath.row]
        cell.price.text = String(prices[indexPath.row])
        cell.average.text = String(averages[indexPath.row])

//but is there something I need to add here to keep the correct Stepper and Label for each class?

    return cell
}

One of the already asked questions includes a protocol and another function in the ViewController like this

protocol ReviewCellDelegate{
    func stepperButton(sender: ReviewTableViewCell)
}

func stepperButton(sender: ReviewTableViewCell) {
    if let indexPath = tableView.indexPathForCell(sender){
        print(indexPath)
    }
}

I don't know if this is the approach I should be trying to take. I am looking for the simplest solution, but I am having trouble putting the pieces together.

Any help is appreciated. Thanks.


回答1:


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.




回答2:


NOTE: MY Cell class is just normal..All changes are in viewcontroller class

class cell: UITableViewCell {

    @IBOutlet weak var ibAddButton: UIButton!
    @IBOutlet weak var ibStepper: UIStepper!
    @IBOutlet weak var ibCount: UILabel!
    @IBOutlet weak var ibLbl: UILabel!
}

1.define empty int array [Int]()

var countArray = [Int]()

2.append countArray with all zeros with the number of data u want to populate in tableview

 for arr in self.responseArray{
        self.countArray.append(0)
   }

3.in cell for row at

func tableView(_ tableView: UITableView, cellForRowAt indexPath:
 IndexPath) -> UITableViewCell {

         let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! cell
         let dict = responseArray[indexPath.row] as? NSDictionary ?? NSDictionary()
         cell.ibLbl.text = dict["name"] as? String ?? String()
         if countArray[indexPath.row] == 0{
             cell.ibAddButton.tag = indexPath.row
             cell.ibStepper.isHidden = true
             cell.ibAddButton.isHidden = false
             cell.ibCount.isHidden = true
             cell.ibAddButton.addTarget(self, action: #selector(addPressed(sender:)), for: .touchUpInside)
         }else{
             cell.ibAddButton.isHidden = true
             cell.ibStepper.isHidden = false
             cell.ibStepper.tag = indexPath.row
             cell.ibCount.isHidden = false
             cell.ibCount.text = "\(countArray[indexPath.row])"
             cell.ibStepper.addTarget(self, action: #selector(stepperValueChanged(sender:)), for: .valueChanged)}
    return cell
     }

4.objc functions

 @objc func stepperValueChanged(sender : UIStepper){
     if sender.stepValue != 0{
         countArray[sender.tag] = Int(sender.value)
     }
     ibTableView.reloadData()
 }
 @objc func addPressed(sender : UIButton){

     countArray[sender.tag] = 1//countArray[sender.tag] + 1
     ibTableView.reloadData()
 }


来源:https://stackoverflow.com/questions/42876739/swift-increment-label-with-stepper-in-tableview-cell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!