Nhat Nguyen
Nhat Nguyen

Reputation: 27

Updating button events in Swift?

I am creating a Check List app and trying to update button event which is set images itself after clicked.

Here is my code:

protocol CustomeCellDelegate { 
   func cell(cell: UITableViewCell, updateTheButton button: UIButton)
}

class Cells: UITableViewCell, UITextFieldDelegate {

@IBOutlet weak var checkBox: UIButton!
    var buttonPressed = true
@IBAction func checkBoxAction(_ sender: UIButton) {
    if buttonPressed {
        sender.setImage(UIImage(named: "checkBoxB"), for: UIControlState.normal)
        buttonPressed = false
    } else {
        sender.setImage(UIImage(named:""), for: UIControlState.normal)
        buttonPressed = true
    }
}
 @objc func recordButtonImage(_ button: UIButton) {
    cellDelegate?.cell(cell: self, updateTheButton: button)  // cell notify the button that touched.
}
override func awakeFromNib() {
    checkBox.addTarget(self, action: #selector(recordButtonImage(_:)), for: UIControlEvents.touchUpInside)  
    }
}

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, CustomeCellDelegate {

@IBOutlet weak var tableView: UITableView!

var myImages: [UIImage?]!

override func viewDidLoad() {
  super.viewDidLoad()
    self.tableView.delegate   = self
    self.tableView.dataSource = self
    myImages = Array(repeatElement(nil, count: 50))
    let nib = UINib(nibName: "Cells", bundle: nil)
    tableView.register(nib, forCellReuseIdentifier: "Cells")
 }

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

internal func tableView(_ tableView:UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "theCells") as? Cells
        cell?.theTextField.delegate = self
        cell?.cellDelegate = self
        cell?.checkBox.setImage(myImages[indexPath.row], for: UIControlState.normal)

    return cell!        
}

// This function from protocol and it helps to update button images.
func cell(cell: UITableViewCell, updateTheButton button: UIButton) {
    print("Delegate method Update Button Images.")
    if let indexPath = tableView.indexPath(for: cell), let buttonImage = button.image(for: UIControlState.normal) {
        myImages[indexPath.row] = buttonImage
    }
}

I would like to update both events of the button that set image after checked and unchecked. Therefore, my table view can dequeue Reusable Cell and have those events updated.

But the result is just one event of button which is checked updated but not the unchecked one. The checked button still repeats whatever I do to uncheck it.

Upvotes: 1

Views: 457

Answers (2)

Nirmalsinh Rathod
Nirmalsinh Rathod

Reputation: 5186

The best way to handle UIButton is using its own state.

You need to hold current state value in one array. So you can keep the state in cellForRow and other things. By default set all state to false.

In CellForRow, just put below code:

  YOUR_BUTTON.isSelected = aryState[indexPath.row] as! Bool

Set image for your button

YOUR_BUTTON.setImage(UIImage(named: NORMAL_IMAGE), for: .normal)
YOUR_BUTTON.setImage(UIImage(named: SELECTED_IMAGE), for: .selected)

Just change button state when it clicked:

@IBAction func checkBoxAction(_ sender: UIButton) {
    let button = sender
    button.isSelected = !button.isSelected
}

Upvotes: 0

Inder Kumar Rathore
Inder Kumar Rathore

Reputation: 39988

I think you don't need recordButtonImage method, you should call the delegate method from the button tapped action i.e. checkBoxAction, just like below

class Cells: UITableViewCell, UITextFieldDelegate {
  @IBOutlet weak var checkBox: UIButton!
  var buttonPressed = true
  @IBAction func checkBoxAction(_ sender: UIButton) {
    if buttonPressed {
      sender.setImage(UIImage(named: "checkBoxB"), for: UIControlState.normal)
      buttonPressed = false
    } else {
      sender.setImage(UIImage(named:""), for: UIControlState.normal)
      buttonPressed = true
    }
    // cell notify the button that touched.
    cellDelegate?.cell(cell: self, updateTheButton: button)
  }
}

Also your data source method, doesn't tell the cell whether the button was pressed or not. It just sets the image but doesn't set the variable buttonPressed

 internal func tableView(_ tableView:UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCell(withIdentifier: "theCells") as? Cells
  cell?.theTextField.delegate = self
  cell?.cellDelegate = self
  cell?.checkBox.setImage(myImages[indexPath.row], for: UIControlState.normal)

  return cell!
}

Upvotes: 1

Related Questions