Search code examples
swiftstatictableviewuilabelstepper

Change the UILabel when a static variable changes


I have a CartItem struct where I store the items that I show in a UITableView My UITableView is in CartViewController. I use custom cell for my table view. Here is my custom cell:

class CartItemCell: UITableViewCell {

@IBOutlet weak var productImage: UIImageView!
@IBOutlet weak var productName: UILabel!
@IBOutlet weak var productPrice: UILabel!
@IBOutlet weak var productTotalPrice: UILabel!
@IBOutlet weak var stepper: UIStepper!



override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

var cellIndex: Int?

var product: CartItem?{
    didSet{
    
    // change the cell in table view when first 
    // initialized and when stepper value is changed 
    .
    .
    .
}

@IBAction func stepperValueChanged(_ sender: UIStepper) {
    CartItem.cartItems[self.cellIndex!].number = Int(sender.value)
    self.product?.number = CartItem.cartItems[self.cellIndex!].number
    }
}

In CartViewController I have totalPrice UILabel which gets its value from CartItem.totalPrice static variable. CartItem.totalPrice's value is calculated and changed every time UIStepper in my UITableViewCell is clicked. Here is the summary of CartViewController

class CartViewController: UIViewController{

@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var cartLabel: UILabel!
@IBOutlet weak var totalPrice: UILabel!

var items = CartItem.cartItems

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(UINib(nibName: "CartItemCell", bundle: nil), forCellReuseIdentifier: "ReusableCell")
    self.totalPrice.text = String(Int(CartItem.totalPrice))
    tableView.reloadData()
}
}


extension CartViewController: UITableViewDataSource{

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return items.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! CartItemCell
    
    cell.product = items[indexPath.item]
    cell.cellIndex = indexPath.item
    return cell
}

}



I want totalPrice label in the CartViewController changed every time CartItem.totalPrice is changed. I change the value of the CartItem.totalPrice in my CartItemCell



Thank you


Solution

  • Use delegate or closures to update value from tableviewcell to viewController

    Protocol CartItemProtocol: AnyObject{
        func valueUpdated() 
    }
    
    class CartItemCell: UITableViewCell {
    
    @IBOutlet weak var productImage: UIImageView!
    @IBOutlet weak var productName: UILabel!
    @IBOutlet weak var productPrice: UILabel!
    @IBOutlet weak var productTotalPrice: UILabel!
    @IBOutlet weak var stepper: UIStepper!
    weak var delegate: CartItemProtocol?
    
    
    override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
    }
    
    var cellIndex: Int?
    
    var product: CartItem?{
        didSet{
    
        // change the cell in table view when first 
        // initialized and when stepper value is changed 
        .
        .
        .
    }
    
    @IBAction func stepperValueChanged(_ sender: UIStepper) {
        CartItem.cartItems[self.cellIndex!].number = Int(sender.value)
        self.product?.number = CartItem.cartItems[self.cellIndex!].number
       self.delegate.valueUpdated()
        }
    }
    

    And set delegate in cellforRow

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> 
    UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! CartItemCell
    
        cell.product = items[indexPath.item]
        cell.cellIndex = indexPath.item
        cell.delegate = self
        return cell
    }
    

    And Update label in delegate conformation

    extension CartViewController:CartItemProtocl{
        self.totalPrice.text = String(Int(CartItem.totalPrice))
    }