amp.dev
amp.dev

Reputation: 470

In swift, how to manage two buttons in same custom tableview cell?

I am trying to manage two buttons in same custom tableview cell. Added two buttons named Yes and No. If yes button is selected the No button will be inactive and Yes button became active.

Here is the image what I need

enter image description here

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell") as! TableViewCell
    cell.yesButton.tag = 101
    cell.noButton.tag = 102
    cell.yesButton.addTarget(self, action: #selector(buttonClicked(sender:)), for: UIControl.Event.touchUpInside)
    cell.noButton.addTarget(self, action: #selector(buttonClicked(sender:)), for: UIControl.Event.touchUpInside)
    return cell
}

 @objc func buttonClicked(sender: AnyObject) {
    let buttonPosition = (sender as AnyObject).convert(CGPoint.zero, to: tableList)
    let indexPath = tableList.indexPathForRow(at: buttonPosition)
    if sender.tag == 101 {
        if indexPath != nil {
            print("Cell indexpath = \(String(describing: indexPath?.row))")
        }
    }

    if sender.tag == 102 {
        if indexPath != nil {
            print("Cell indexpath = \(String(describing: indexPath?.row))")
        }
    }
}

Upvotes: 0

Views: 1919

Answers (4)

Sagar Thummar
Sagar Thummar

Reputation: 2124

Simple 3 step process...!!

  1. Define Model Class
  2. Prepare tableView Cell & handle actions
  3. Set up tableView in view controller

Let's start implementation:

1) Define Model Class

In UI, we have a information like question & it's answer (Yes/No). So design model respectively.

//MARK:- Class Declaration -
class Question {
      let questionText: String
      var answerState: Bool?

      init(question: String) {
           self.questionText = question
      }
}

2. Prepare tableView Cell & handle actions

Create a custom tableView cell with Question Label, Yes Button & No Button. Link that view with respected @IBOutlets & @IBActions.

import UIKit

class TableViewCell: UITableViewCell {
      @IBOutlet weak var questionLabel: UILabel!
      @IBOutlet weak var yesButton: UIButton!
      @IBOutlet weak var noButton: UIButton!

      var question: Question?
      var toggle: Bool? {
          didSet {
                 question?.answerState = toggle
                 //Do buttons operations like...
                 if let isToggle = toggle {
                    yesButton.backgroundColor = isToggle ? .green : .gray
                    noButton.backgroundColor = isToggle ? .gray : .green
                 } else {
                    yesButton.backgroundColor =  .gray
                    noButton.backgroundColor = .gray
                 }
          }
      }

      func prepareView(forQuestion question: Question) {
           self.question = question
           questionLabel.text = question.questionText
           toggle = question.answerState
      }

      //Yes Button - IBAction Method
      @IBAction func yesButtonTapped(_ sender: UIButton) {
            toggle = true
      }

      //No Button - IBAction Method
      @IBAction func noButtonTapped(_ sender: UIButton) {
            toggle = false
      }
}

3. Set up tableView in view controller

class ViewController: UIViewController {

    //Prepare questions model array to design our tableView data source
    let arrQuestions: [Question] = [Question(question: "Do you speak English?"), Question(question: "Do you live in Chicago?")]
}

//MARK:- UITableView Data Source & Delegate Methods -
extension ViewController: UITableViewDataSource, UITableViewDelegate {

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let tableViewCell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as? TableViewCell else {
            return UITableViewCell()
        }
        tableViewCell.prepareView(forQuestion: arrQuestions[indexPath.row])
        return tableViewCell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80.0
    }
}

Upvotes: 0

PGDev
PGDev

Reputation: 24341

Create a model to main the state of yesButton and noButton for each tableViewCell, i.e.

class Model {
    var isYesSelected = false
    var isNoSelected = false
}

Create a custom UITableViewCell with Outlets of yesButton and noButton.

Create a single @IBAction for both the buttons and handle their UI based on which button is tapped.

Also, use a buttonTapHandler to identify the row in which the button is tapped. It will be called everytime a button is tapped. We'll be setting this when creating the instance of TableViewCell in tableView(_:cellForRowAt:).

class TableViewCell: UITableViewCell {
    @IBOutlet weak var yesButton: UIButton!
    @IBOutlet weak var noButton: UIButton!

    var buttonTapHandler: (()->())?
    var model: Model?

    override func prepareForReuse() {
        super.prepareForReuse()
        yesButton.backgroundColor = .gray
        noButton.backgroundColor = .gray
    }

    func configure(with model: Model) {
        self.model = model
        self.updateUI()
    }

    @IBAction func onTapButton(_ sender: UIButton) {
        model?.isYesSelected = (sender == yesButton)
        model?.isNoSelected = !(sender == yesButton)
        self.updateUI()
    }

    func updateUI() {
        yesButton.backgroundColor = (model?.isYesSelected ?? false) ? .green : .gray
        noButton.backgroundColor = (model?.isNoSelected ?? false) ? .green : .gray
    }
}

UITableViewDataSource's tableView(_:cellForRowAt:) method goes like,

let numberOfCells = 10
var models = [Model]()

override func viewDidLoad() {
    super.viewDidLoad()
    (0..<numberOfCells).forEach { _ in
        self.models.append(Model())
    }
}

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! TableViewCell
    cell.configure(with: models[indexPath.row])
    cell.buttonTapHandler = {
        print(indexPath.row)
    }
    return cell
}

To get the totalPoints, count the models with isYesSelected = true, i.e.

let totalPoints = models.reduce(0) { (result, model) -> Int in
    if model.isYesSelected {
        return result + 1
    }
    return 0
}
print(totalPoints)

Upvotes: 4

emrcftci
emrcftci

Reputation: 3516

  • Create basic tableView and configure dataSource functions image1

  • Create tableView cell with two buttons image2

  • Create cell class with buttons outlets and actions image3

  • Result of this code

result gif

Enjoy!

Upvotes: -1

Rushabh Shah
Rushabh Shah

Reputation: 402

Get that Button using your Tag like below and after that, you can change the value as per you want.

var tmpButton = self.view.viewWithTag(tmpTag) as? UIButton

Upvotes: 0

Related Questions