Macness Macness - 2 months ago 6
iOS Question

Update model through UIButton within a UITableViewCell

In MainVC.swift I'm capturing the tag of my custom "PlayerCell". I want to press the

increaseBtn
(UIButton) which will increment the
playerLbl.text
(UILabel) by one but also update my model
(PlayerStore.player.playerScore: Int)


Main.swift:

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

if let cell = tableView.dequeueReusableCell(withIdentifier: "PlayerCell", for: indexPath) as? PlayerCell {

let player = players[indexPath.row]

cell.updateUI(player: player)

cell.increaseBtn.tag = indexPath.row
cell.decreaseBtn.tag = indexPath.row

return cell

} else {
return UITableViewCell()
}

}


PlayerCell.swift

class PlayerCell: UITableViewCell {

@IBOutlet weak var playerLbl: UILabel!
@IBOutlet weak var increaseBtn: UIButton!
@IBOutlet weak var decreaseBtn: UIButton!
@IBOutlet weak var scoreLbl: UILabel!
@IBOutlet weak var cellContentView: UIView!

func updateUI(player: Player){
playerLbl.text = player.playerName
scoreLbl.text = "\(player.playerScore)"
cellContentView.backgroundColor = player.playerColor.color
}

@IBAction func increaseBtnPressed(_ sender: AnyObject) {
let tag = sender.tag
// TODO: send this tag back to MainVC?

}

Answer

I would use the delegate pattern in this case. Create a protocol that Main.swift implements, and that PlayerCell.swift uses as an optional property. So for example:

protocol PlayerIncrementor {
    func increment(by: Int)
    func decrement(by: Int)
}

Then use an extension on Main.swift to implement this protocol

extension Main: PlayerIncrementor {
    func increment(by: int) {
        //not 100% what you wanted to do with the value here, but this is where you would do something - in this case incrementing what was identified as your model
        PlayerStore.player.playerScore += by
    }
}

Inside of PlayerCell.swift, add a delegate property and call the delegate increment method in your @IBAction

class PlayerCell: UITableViewCell {

    var delegate: PlayerIncrementor?

    @IBOutlet weak var increaseBtn: UIButton!

    @IBAction func increaseBtnPressed(_ sender: AnyObject) {
        let tag  = sender.tag

        //call the delegate method with the amount you want to increment
        delegate?.increment(by: tag)    
    }

Lastly - to make it all work, assign Main as the delegate to the PlayerCell UITableViewCell.

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

    if let cell = tableView.dequeueReusableCell(withIdentifier: "PlayerCell", for: indexPath) as? PlayerCell {

   //self, in this case is Main - which now implements PlayerIncrementor 
   cell.delegate = self

   //etc