Swift 3.0 How to Change a Button Title Using TableView Cells - ios

I have a table view with subclassed table view cells. I have attached a button and hooked this up to the table view cell's VC. I want the button to say 'Add' upon loading, 'Subtract' when clicked and back to 'Add' when clicked again. But I am having trouble understanding how I can relate the row number with the state of the button.
VC with table view:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TVCell
cell.cellDelegate = self
if (searchActive) {
cell.textLabel?.text = filtered[indexPath.row]
} else {
cell.textLabel?.text = data[indexPath.row]
}
return cell
}
func didPressButton(cell: TVCell) {
guard let indexPath = self.tableView.indexPath(for: cell) else {
return
}
print("Button tapped on row \(indexPath.row)")
}
VC for table view cell:
protocol TVCellDelegate : class {
func didPressButton(cell: TVCell)
}
class TVCell: UITableViewCell {
#IBOutlet weak var addButton: UIButton!
weak var cellDelegate: TVCellDelegate?
override func prepareForReuse() {
super.prepareForReuse()
self.cellDelegate = nil
}
// connect the button from your cell with this method
#IBAction func buttonPressed(sender: UIButton) {
self.cellDelegate?.didPressButton(cell: self)
}
}

Store the buttons' state in your view controller and change the text after reusing and button pressing.
VC with TableView:
var isSubtracting = [IndexPath: Bool]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TVCell
cell.cellDelegate = self
if isSubtracting[indexPath] ?? false {
cell.addButton.setTitle("Add", for: .normal)
} else {
cell.addButton.setTitle("Subtract", for: .normal)
}
cell.indexPath = indexPath
if(searchActive) {
cell.textLabel?.text = filtered[indexPath.row]
} else {
cell.textLabel?.text = data[indexPath.row]
}
return cell
}
func didPressButton(indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) as? TVCell else {
return
}
if isSubtracting[indexPath] ?? false {
isSubtracting[indexPath] = false
cell.addButton.setTitle("Subtract", for: .normal)
} else {
isSubtracting[indexPath] = true
cell.addButton.setTitle("Add", for: .normal)
}
}
VC for table view cell:
protocol TVCellDelegate : class {
func didPressButton(indexPath: IndexPath)
}
class TVCell: UITableViewCell {
#IBOutlet weak var addButton: UIButton!
weak var cellDelegate: TVCellDelegate?
var indexPath: IndexPath!
override func prepareForReuse() {
super.prepareForReuse()
self.cellDelegate = nil
}
// connect the button from your cell with this method
#IBAction func buttonPressed(sender: UIButton) {
self.cellDelegate?.didPressButton(indexPath: indexPath)
}
}

You can add the title's for the states of buttons like this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TVCell
cell.cellDelegate = self
cell.indexPath = indexPath
cell.addButton.setTitle("Add",for: .normal)
cell.addButton.setTitle("Subtract",for: .selected)
if(searchActive) {
cell.textLabel?.text = filtered[indexPath.row]
} else {
cell.textLabel?.text = data[indexPath.row]
}
return cell
}
and tableViewCell
protocol TVCellDelegate : class {
func didPressButton(indexPath: IndexPath)
}
class TVCell: UITableViewCell {
#IBOutlet weak var addButton: UIButton!
weak var cellDelegate: TVCellDelegate?
var indexPath: IndexPath!
override func prepareForReuse() {
super.prepareForReuse()
self.cellDelegate = nil
}
// connect the button from your cell with this method
#IBAction func buttonPressed(sender: UIButton) {
if(sender.isSelected){
sender.isSelected = false
}else{
sender.isSelected = true
}
self.cellDelegate?.didPressButton(indexPath: indexPath)
}
}

Related

load three xib in UITableView on clicking three different button

There are three button in a UIView and a UITableView below the UIView i want to load xib on click on button. if first button is click load new xib if second button is click load approved xib if third button is click load rejected xib
#IBOutlet weak var newButton: UIButton!
#IBOutlet weak var approvedButton: UIButton!
#IBOutlet weak var rejectedButton: UIButton!
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var approvedDownLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
approvedDownLabel.isHidden = true
rejectedDownLbl.isHidden = true
addNewTblview.dataSource = self
addNewTblview.delegate = self
newButton.isSelected = true
self.addNewTblview.register(UINib(nibName: "AddInstructorNewCell", bundle: nil), forCellReuseIdentifier: "AddInstructorNewCell")
self.addNewTblview.register(UINib(nibName: "ApprovedCell", bundle: nil), forCellReuseIdentifier: "ApprovedCell")
self.addNewTblview.register(UINib(nibName: "RejectedCell", bundle: nil), forCellReuseIdentifier: "RejectedCell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if newButton.isSelected {
let cell = self.addNewTblview.dequeueReusableCell(withIdentifier: "AddInstructorNewCell", for: indexPath) as! AddInstructorNewCell
return cell
} else if approvedButton.isSelected {
let cell = self.addNewTblview.dequeueReusableCell(withIdentifier: "ApprovedCell", for: indexPath) as! ApprovedCell
return cell
} else {
let cell = self.addNewTblview.dequeueReusableCell(withIdentifier: "RejectedCell", for: indexPath) as! RejectedCell
return cell
}
// return UITableViewCell()
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if newButton.isSelected {
return 170
} else if approvedButton.isSelected{
return 165
}else {
return 178
}
// return 170
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
First you create tree cell class with .xib.
#IBAction func btnNewClick(_ sender:UIButton)
{
self.approvedButton.isSelected = false
self.rejectedButton.isSelected = false
self.Yourtbl.reloadData()
}
set action btnapprovedClick button
#IBAction func btnapprovedClick(_ sender:UIButton)
{
self.approvedButton.isSelected = true
self.rejectedButton.isSelected = false
self.newButton.isSelected = false
self.Yourtbl.reloadData()
}
set action btnrejectedClick button
#IBAction func btnrejectedClick(_ sender:UIButton)
{
self.approvedButton.isSelected = false
self.rejectedButton.isSelected = true
self.newButton.isSelected = false
self.Yourtbl.reloadData()
}
Why don't you use enum? See the code below for further reference.
import UIKit
enum ViewType {
case new, approved, rejected
}
class ViewController {
private var viewType: ViewType = .new
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch viewType {
case .new :
let cell = self.addNewTblview.dequeueReusableCell(withIdentifier: "AddInstructorNewCell", for: indexPath) as! AddInstructorNewCell
return cell
case .approved:
let cell = self.addNewTblview.dequeueReusableCell(withIdentifier: "ApprovedCell", for: indexPath) as! ApprovedCell
return cell
case .rejected:
let cell = self.addNewTblview.dequeueReusableCell(withIdentifier: "RejectedCell", for: indexPath) as! RejectedCell
return cell
}
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
switch viewType {
case .new:
return 170
case .approved:
return 165
case .rejected:
return 178
}
}
#IBAction func btnNewClick(_ sender:UIButton)
{
viewType = .new
tableView.reloadData()
}
#IBAction func btnapprovedClick(_ sender:UIButton)
{
viewType = .approved
tableView.reloadData()
}
#IBAction func btnrejectedClick(_ sender:UIButton)
{
viewType = .rejected
tableView.reloadData()
}
}

UITableview Update Single Cell

I got a play button on my tableview custom cell, whenever I tapped the play button. I want the selected button image to change to pause image.
The issue is that all the other buttons images are getting updated.
So all the images are changing to the pause image, instead of the selected button.
I tried to get the indexpath of the button tapped and reload only that row, but that doesn't seem to make a difference.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let playerCell = tableView.dequeueReusableCell(withIdentifier: "playerCell", for: indexPath) as! PlayerCell
let item = subcategory?.items?[indexPath.row]
// Tap gestures extension for cell button action
playerCell.playPause.addTapGestureRecognizer {
AudioController.shared.setupPlayer(item: item)
if let selectedCell = tableView.cellForRow(at: indexPath) as? PlayerCell {
selectedCell.playPause.setImage(#imageLiteral(resourceName: "pause"), for: .normal)
tableView.reloadRows(at: [IndexPath(row: indexPath.row, section: 1)], with: .none)
}
print("index \(indexPath)")
}
What you can do is add a tag to the button. So within the method that you create the cells override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell, you add a tag to the button within that cells that represents the indexPath. Then from within the selector that you assign the button, you can get the cell that you want to alter.
For example:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath)
cell.button.tag = indePath.row
cell.button.addTarget(self, action: #selector(yourSelector(_sender:)), for: .touchUpInside)
}
func yourSelector(_sender: UIButton){
let cell = tableView.cellForRow(at: IndexPath(row: sender.tag, section: 0)) as! YourCellType
// Change the image, play/pause audio for that cell
}
When you tap on the button in cell, tableView(_:didSelectRowAt:) won't be trigger, so I suggest using delegate to detect button action.
And you need to keep tracking the change of the cell's button status.
For example:
PlayCell.swift
protocol PlayCellDelegate: class {
func playCellPlayButtonDidPress(at indexPath: IndexPath)
}
class PlayerCell: UITableViewCell {
let playButton: UIButton = {
let button = UIButton()
button.addTarget(self, action: #selector(playButtonPressed(_:)), for: .touchUpInside)
return button
}()
weak var delegate: PlayCellDelegate?
var item: MyItem? {
didSet {
if item?.status == .paused {
// set pause image for playButton here
} else if item?.status == .playing {
// set play image for playButton here
}
}
}
var indexPath: IndexPath?
#objc func playButtonPressed(_ sender: UIButton) {
guard let indexPath = self.indexPath else { return }
delegate?.playCellPlayButtonDidPress(at: indexPath)
}
}
Model.swift
struct Subcategory {
// ...
var items: [MyItem]?
}
struct MyItem {
// ...
var status: Status.stop
enum Status {
case playing, paused, stopped // etc..
}
}
TableViewController.swift
class TableViewController: UITableViewController, PlayCellDelegate {
private var subcategory: Subcategory?
private let cellId = "Cell"
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as? PlayerCell {
cell.delegate = self
cell.item = subcategory?.items?[indexPath.row]
cell.indexPath = indexPath
return cell
}
return UITableViewCell()
}
func playCellPlayButtonDidPress(at indexPath: IndexPath) {
// you only need to change model here, and reloadRows will update the cell.
if subcategory?.items?[indexPath.row].status == .play {
subcategory?.items?[indexPath.row].status = .pause
} // other logic..
tableView.reloadRows(at: [indexPath], with: .none)
}
}
Hope it helps!

Swift tableview cell select to change checkbox image

I am trying to implement custom button check box in tableview cell. I have done checkbox when user clicks cell button it can change check and uncheck but if you click tableview cell also I needs to operate the check box
If possible please give some idea for radio button functionality because I am doing both.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
cell.myCellLabel.text = self.animals[indexPath.row]
if selectedRows.contains(indexPath)
{
cell.checkBox.setImage(UIImage(named:"check.png"), for: .normal)
}
else
{
cell.checkBox.setImage(UIImage(named:"uncheck.png"), for: .normal)
}
cell.checkBox.tag = indexPath.row
cell.checkBox.addTarget(self, action: #selector(checkBoxSelection(_:)), for: .touchUpInside)
return cell
}
// method to run when table view cell is tapped
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
}
#objc func checkBoxSelection(_ sender:UIButton)
{
let selectedIndexPath = IndexPath(row: sender.tag, section: 0)
if self.selectedRows.contains(selectedIndexPath)
{
self.selectedRows.remove(at: self.selectedRows.index(of: selectedIndexPath)!)
}
else
{
self.selectedRows.append(selectedIndexPath)
}
self.tableView.reloadData()
}
You can get the selected cell in didSelectRowAt delegate and set the checkmark.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) as? MyCustomCell else {
return
}
if self.selectedRows.contains(indexPath) {
self.selectedRows.remove(at: self.selectedRows.index(of: indexPath)!)
cell.checkBox.setImage(UIImage(named:"unccheck.png"), for: .normal)
} else {
self.selectedRows.append(indexPath)
cell.checkBox.setImage(UIImage(named:"check.png"), for: .normal)
}
}
// https://stackoverflow.com/questions/47300399/how-to-select-table-view-row-selection-with-custom-checkbox-button
import UIKit
class MyCustomCell: UITableViewCell {
#IBOutlet weak var checkBox: UIButton!
#IBOutlet weak var myCellLabel: UILabel!
}
class UpdateViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
// These strings will be the data for the table view cells
var animals: [String] = ["Horse", "Cow", "Camel", "Sheep", "Goat"]
var selectedRows:[IndexPath] = []
// These are the colors of the square views in our table view cells.
// In a real project you might use UIImages.
let colors = [UIColor.blue, UIColor.yellow, UIColor.magenta, UIColor.red, UIColor.brown]
// Don't forget to enter this in IB also
let cellReuseIdentifier = "cell"
override func viewDidLoad() {
super.viewDidLoad()
// Remove unused array
tableView.tableFooterView = UIView()
//tableView.allowsSelection = false
tableView.delegate = self
tableView.dataSource = self
}
// number of rows in table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.animals.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
cell.myCellLabel.text = self.animals[indexPath.row]
if selectedRows.contains(indexPath)
{
cell.checkBox.setImage(UIImage(named:"check.png"), for: .normal)
}
else
{
cell.checkBox.setImage(UIImage(named:"uncheck.png"), for: .normal)
}
cell.checkBox.tag = indexPath.row
cell.checkBox.addTarget(self, action: #selector(checkBoxSelection(_:)), for: .touchUpInside)
return cell
}
// method to run when table view cell is tapped
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
guard let cell = tableView.cellForRow(at: indexPath) as? MyCustomCell else {
return
}
if self.selectedRows.contains(indexPath) {
self.selectedRows.remove(at: self.selectedRows.index(of: indexPath)!)
cell.checkBox.setImage(UIImage(named:"uncheck.png"), for: .normal)
} else {
self.selectedRows.append(indexPath)
cell.checkBox.setImage(UIImage(named:"check.png"), for: .normal)
let indexPath = tableView.indexPathForSelectedRow //optional, to get from any UIButton for example
let currentCell = tableView.cellForRow(at: indexPath!) as! MyCustomCell
print(currentCell.myCellLabel.text ?? "")
}
}
#objc func checkBoxSelection(_ sender:UIButton)
{
let selectedIndexPath = IndexPath(row: sender.tag, section: 0)
if self.selectedRows.contains(selectedIndexPath)
{
self.selectedRows.remove(at: self.selectedRows.index(of: selectedIndexPath)!)
}
else
{
self.selectedRows.append(selectedIndexPath)
let center = sender.center
let point = sender.superview!.convert(center, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: point)
let cell = self.tableView.cellForRow(at: indexPath!) as! MyCustomCell //Add superview on the basis of your button hierarchy in the cell
let cell_labelvalue = cell.myCellLabel!.text
print(cell_labelvalue ?? "")
}
self.tableView.reloadData()
}
#IBAction func selectAllBtnAction(_ sender: UIBarButtonItem) {
self.selectedRows = getAllIndexPaths()
self.tableView.reloadData()
}
func getAllIndexPaths() -> [IndexPath] {
var indexPaths: [IndexPath] = []
for j in 0..<tableView.numberOfRows(inSection: 0) {
indexPaths.append(IndexPath(row: j, section: 0))
}
return indexPaths
}
#IBAction func cancelPopup(_ sender: Any) {
self.removeAnimate()
}
#IBAction func donePopUp(_ sender: AnyObject) {
self.removeAnimate()
}
func showAnimate()
{
self.view.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
self.view.alpha = 0.0;
UIView.animate(withDuration: 0.25, animations: {
self.view.alpha = 1.0
self.view.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
});
}
func removeAnimate()
{
UIView.animate(withDuration: 0.25, animations: {
self.view.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
self.view.alpha = 0.0;
}, completion:{(finished : Bool) in
if (finished)
{
self.view.removeFromSuperview()
}
});
}
}

Increment Label Value with UIStepper in UITableViewCell

I want to be able to use a UIStepper that is located in each tableview row. I would like each UIStepper to update a label in the same tableview row that the UIStepper is in.
The code that I am trying is as follows
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartListCell = tableView.dequeueReusableCell(withIdentifier: reuseCartListingCellIdentifier, for: indexPath) as? CartListingItemTableViewCell
cartListCell?.UI_STEPPER_NAME.value = VALUE_FROM_ARRAY
return cartListCell!
}
#IBAction func CartStoreQtyStepperAction(_ sender: UIStepper) {
// I need to update the value of a label in the tableview cell that tapped
}
UPDATED IMPLEMENTATION
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cartListCell?.CartListingProductQtyStepperOutlet.tag = indexPath.row
cartListCell?.CartListingProductQtyStepperOutlet.addTarget(self, action: #selector(self.CartStoreQtyStepperAction(_:)), for: UIControlEvents.valueChanged)
cartListCell?.tag = Int(CartStoreItemIdArray [indexPath.row])!
return cartListCell!
}
#IBAction func CartStoreQtyStepperAction(_ sender: UIStepper)
{
let stepperValue = Int(sender.value)
let indexPath = IndexPath(row: stepperValue, section: 0)
print(stepperValue)
if let cell = yourTableView.cellForRow(at: indexPath) as? CartListingItemTableViewCell
{
print(cell?.tag)
}
}
I am not able to access the tableview cell and the label in that when I am doing it like this. Can someone guide me how to do this?
// Custom tableview cell code
class CartListingItemTableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var stepper: UIStepper!
}
// your view controller code (tableview data source)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartListCell = tableView.dequeueReusableCell(withIdentifier: reuseCartListingCellIdentifier, for: indexPath) as? CartListingItemTableViewCell
let stepperValue = yourArray[indexPath.row]
cartListCell?.label.text = String(stepperValue) ?? "0"
cartListCell?.stepper.value = Int(stepperValue) ?? 0
cartListCell?.stepper.tag = indexPath.row
cartListCell?.stepper.addTarget(self, action: #selector(self.stepperValueChanged(_:)), for: UIControlEvents.valueChanged)
return cartListCell!
}
// handle stepper value change action
#IBAction func stepperValueChanged(_ stepper: UIStepper) {
let stepperValue = Int(stepper.value)
print(stepperValue) // prints value
let indexPath = IndexPath(row: stepperValue, section: 0)
if let cell = yourTableView.cellForRow(at: indexPath) as? CartListingItemTableViewCell {
cell.label.text = String(stepperValue)
yourValueArray[index] = stepperValue
}
}
This is a solution for Swift 4 using NSKeyValueObservation
First of all you need a property in your data model to keep the current value of the stepper.
var counter = 0.0
In the custom cell create outlets for the stepper and the label and a property for the observation. Connect the outlets.
#IBOutlet weak var stepper : UIStepper!
#IBOutlet weak var label : UILabel!
var observation : NSKeyValueObservation?
In the controller in cellForRow add the observer, dataSourceArray is the data source array.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartListCell = tableView.dequeueReusableCell(withIdentifier: reuseCartListingCellIdentifier, for: indexPath) as! CartListingItemTableViewCell
let item = dataSourceArray[indexPath.row]
cartListCell.stepper.value = item.counter
cartListCell.label.text = "\(item.counter)"
cartListCell.observation = cell.stepper.observe(\.value, options: [.new]) { (_, change) in
cartListCell.label.text = "\(change.newValue!)"
item.counter = change.newValue!
}
return cartListCell
}
Solution for Swift 4 swift4.
Add these lines in cellforRowAt.
cartListCell.UI_STEPPER_NAME.tag = indexPath.row
cartListCell.UI_STEPPER_NAME.addTarget(self, action: #selector(CartStoreQtyStepperAction), for: .touchUpInside)
To access cell items in the stepper function use this line.
let cartListCell = sender.superview?.superview as! CartListingItemTableViewCell
//check whether your superview is table cell.
//then use the cell instance to update the cell label
Use sender.tag in the function to access particular cell for example.
cartListCell.UI_STEPPER_NAME.text = "\(VALUE_FROM_ARRAY[sender.tag])"
//sender.tag is similar to indexPath.row as we pass the tag value in the cellforRowAt.
//It will work then please accept my answer๐Ÿ‘๐Ÿผ๐Ÿ˜„.
Assign tag value to sender of UIStepper in cellForRowAt and access the change of UIStepper value in CartStoreQtyStepperAction action using same tag.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartListCell = tableView.dequeueReusableCell(withIdentifier: reuseCartListingCellIdentifier, for: indexPath) as? CartListingItemTableViewCell
//Assign tag value
cartListCell?.UI_STEPPER_NAME.tag = indexPath.row
cartListCell?.UI_STEPPER_NAME.value = VALUE_FROM_ARRAY
cartListCell?.stepper.addTarget(self, action: #selector(self.CartStoreQtyStepperAction(_:)), for: UIControlEvents.valueChanged)
return cartListCell!
}
#IBAction func CartStoreQtyStepperAction(_ sender: UIStepper) {
let index = sender.tag
yourValueArray[index] = sender.value
//Reload particular cell for tableView
}

How to Change the image of UIButton when selected which is on tableVIewCell. in Swift 3

I am implementing a like dislike button on the tableview cell but unable to change the image of the button. can anybody help me out using swift 3
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var array: [String] = ["A","B","C","D","E","F"]
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: cell_TableTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "cell_TableTableViewCell") as UITableViewCell! as! cell_TableTableViewCell!
cell.textLabel?.text = array[indexPath.row]
cell.button_Outlet.tag = indexPath.row
cell.button_Outlet.addTarget(self, action: "LikePressed", for: .touchUpInside)
return cell
}
}
func LikePressed(sender : UIButton){
sender.isSelected = !sender.isSelected
}
While designing your custom cell, you can add image for that button for different states
Default
Selected
When you add selector for that button, in that selector you just need to change button's selection state
func buttonTapped(sender : UIButton){
sender.isSelected = !sender.isSelected
}
It's very simple, for example your button is from storyboard. Add make that it custom button.
1) And add tag value in cellForRowAt indexPath:.
2) And set two images for that butoon.
3) Finally fix selected sate.
See my code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: cell_TableTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "cell_TableTableViewCell") as UITableViewCell! as! cell_TableTableViewCell!
cell.textLabel?.text = array[indexPath.row]
//Step 1
cell.button_Outlet.tag = indexPath.row
cell.button_Outlet.addTarget(self, action: "LikePressed", for: .touchUpInside)
//Step 2
cell.button_Outlet.setImage(UIImage(named: "LikeImage"), for: .selected)
cell.button_Outlet.setImage(UIImage(named: "DisLikeImage"), for: .selected)
return cell
}
//Step 3
func btnPressed(sender:UIButton) {
if sender.isSelected == false {
sender.isSelected = true
} else {
sender.isSelected = false
}
}
IBOutlet the UIButton into your cell class(Eg. TableViewCell).
Write a method in ViewController class to detect buttonTap.
Eg:
func dislikeTapped(_ sender: UIButton) {
// set required image to sender
}
In TableView-CellForRow method add target to the button in cell.
Eg:
cell.dislikeButton.addTarget(self, action: #selector(self.dislikeTapped(_:), for: .touchUpInside)
You need to create an array too to maintain the state of button as when you scroll cell that are not visible on screen are removed from memory, so they are dequeued again from one that are visible, if you not maintain the state it will use attributes of cell u dequeued from.
var arrSelectedButtonswitTag = [Int]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: cell_TableTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "cell_TableTableViewCell") as UITableViewCell! as! cell_TableTableViewCell!
cell.textLabel?.text = array[indexPath.row]
//Step 1
cell.button_Outlet.tag = indexPath.row
cell.button_Outlet.addTarget(self, action: "LikePressed", for: .touchUpInside)
//Step 2
cell.button_Outlet.setImage(UIImage(named: "LikeImage"), for: .selected)
cell.button_Outlet.setImage(UIImage(named: "DisLikeImage"), for: .normal)
if arrSelectedButtonswitTag.contain(sender.tag)
sender.isSelected = false
arrSelectedButtonswitTag.remove(sender.tag)
} else {
sender.isSelected = true
arrSelectedButtonswitTag.appen(sender.tag)
}
return cell
}
//Step 3
func btnPressed(sender:UIButton) {
if arrSelectedButtonswitTag.contain(sender.tag)
sender.isSelected = false
arrSelectedButtonswitTag.remove(sender.tag)
} else {
sender.isSelected = true
arrSelectedButtonswitTag.append(sender.tag)
}
}

Resources