How to detect one button in tableview cell - ios

How to detect one button in UITableviewCell, I have 10 UIButton in UITableViewCell, next when I click on UIButton then it detects multiple buttons, (as like odd number list). my UITableView is with paging enabled. Here is my all code.
TableView
class HomeViewController: UIViewController, UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var homeTableView: UITableView!
let mainArray = [["1","2","3","4"],["5","6","7","8"],["9","10","11","12"],["13","14","15","16"]]
override func viewDidLoad() {
super.viewDidLoad()
self.homeTableView.delegate = self
self.homeTableView.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return mainArray.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mainArray[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTableViewCell", for: indexPath) as! HomeTableViewCell
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.view.frame.size.height
}
}
TableViewCell
class HomeTableViewCell: UITableViewCell {
#IBOutlet weak var bookMarkBtn: UIButton!
#IBAction func bookMarkBtnAction(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
if(sender.isSelected == true)
{
sender.setImage(UIImage(named:"favorite_blue"), for: UIControlState.normal)
}
else
{
sender.setImage(UIImage(named:"favorite_white"), for: UIControlState.normal)
}
}
}

To detect a UIButton in a UITableViewCell, you can follow any of the below approaches:
1. Use UIButton IBOutlets
You can create an IBOutlet corresponding to each UIButton in the UITableViewCell and use those outlets to identify which button action is performed.
Example:
class CustomCell: UITableViewCell
{
#IBOutlet weak var button1: UIButton!
#IBOutlet weak var button2: UIButton!
#IBOutlet weak var button3: UIButton!
#IBOutlet weak var button4: UIButton!
#IBOutlet weak var button5: UIButton!
#IBAction func onTapButton(_ sender: UIButton)
{
if sender === button1
{
//button1 specific code here
}
else if sender === button2
{
//button2 specific code here
}
//and so on..
}
}
2. Use UIButton Tag property
You can provide a tag value to each of the UIButton present in the UITableViewCell and then use that tag to identify the specific button.
Example:
class CustomCell: UITableViewCell
{
#IBAction func onTapButton(_ sender: UIButton)
{
if sender.tag == 1
{
//button1 has a tag = 1
//button1 specific code here
}
else if sender.tag == 2
{
//button2 has a tag = 2
//button2 specific code here
}
//and so on..
}
}
Edit:
For setting different images in selected/unselected state of UIButton, you can use storyboard for that:
For Unselected state:
For Selected state:
Let me know if you still face any issues.

In your cellForRowAt method, do add tag number to the buttons
cell.bookMarkBtn.tag = indexPath.row;
Then
#IBAction func bookMarkBtnAction(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
if(sender.tag == 0)
{
...
} else if (sender.tag == 1)
{
...
}
}

Create protocol
protocol HomeTableViewCellDelegate {
func bookMarkBtnTapped(btn: UIButton)
}
class HomeTableViewCell: UITableViewCell {
#IBOutlet weak var bookMarkBtn: UIButton!
//add delegate var for protocol
var delegate: HomeTableViewCellDelegate?
#IBAction func bookMarkBtnAction(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
if(sender.isSelected == true)
{
sender.setImage(UIImage(named:"favorite_blue"), for: UIControlState.normal)
}
else
{
sender.setImage(UIImage(named:"favorite_white"), for: UIControlState.normal)
}
//set this which button is pressed
self.delegate?.bookMarkBtnTapped(btn: sender)
}
}
HomeViewController implement HomeTableViewCellDelegate method
class HomeViewController: HomeTableViewCellDelegate {
func bookMarkBtnTapped(btn: UIButton) {
// here btn is book mark button tapped by user from tableview cell
}
}

Use button tag for this.
In tableViewController
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTableViewCell", for: indexPath) as! HomeTableViewCell
cell.bookMarkBtn.tag = indexPath.row
cell.bookMarkBtn.addTarget(self, action: #selector(self. bookMarkBtnAction), for: .touchUpInside)
return cell
}
#objc func bookMarkBtnAction(sender: UIButton) {
if sender.tag == 0 { //or which indexpath do you want.
//code
} else if sender.tag == 1 {
//code
}
..
}
remove #IBAction func bookMarkBtnAction(_ sender: UIButton) from tableviewcell class

Related

Change button title for selected row in TableView Swift

i have a view controller in which there is a tableview cell having button on it. Button with title add comments. when i click on add comments button then it take me to the next page where textfield is present when i write something in it then press done button then my button title for all the cell changes. But i want only selected row button title should change. Below is my code of table view.
class MyTabViewController: UIViewController {
var addCommentsValueStore: String = "Add Comments"
#IBOutlet weak var tabTableView : ContentWrappingTableView!
#IBAction func addCommentsAction(_ sender: UIButton) {
guard let nextVC = MyCommentsRouter.getMyCommentsViewScreen() else { return }
nextVC.passAddCommentsDelegate = self
self.navigationController?.pushViewController(nextVC, animated: true)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let indetifier = "MyTabTableViewCell"
let cell = tableView.dequeueReusableCell(withIdentifier: indetifier, for: indexPath) as! MyTabTableViewCell
cell.addCommentsButton.setTitle(addCommentsValueStore, for: UIControl.State.normal)
}
}
extension MyTabViewController: AddCommentsDelegate{
func passAddComments(instruction: String) {
addCommentsValueStore = instruction
print(addCommentsValueStore)
}
}
below is the code of next view controller:
import UIKit
protocol AddCommentsDelegate{
func passAddComments(instruction: String)
}
class MyCommentsViewController: UIViewController {
#IBOutlet var addCommentsTextField: UITextField!
var passAddCommentsDelegate: AddCommentsDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func backActionClick(_ sender: UIButton) {
// guard let nextVC = MyTabRouter.getMyTabViewScreen() else { return }
self.navigationController?.popViewController(animated: true)
}
#IBAction func DoneActionClick(_ sender: Any) {
let dataToBeSent = addCommentsTextField.text
self.passAddCommentsDelegate?.passAddComments(instruction: dataToBeSent!)
self.navigationController?.popViewController(animated: true)
}
}
You can do it in this delegate method as below:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
for (id object in cell.superview.subviews) {
if ([object isKindOfClass:[UITableViewCell class]]) {
UITableViewCell *cellNotSelected = (UITableViewCell*)object;
cellNotSelected.textLabel.textColor = [UIColor blackColor];
}
}
cell.textLabel.textColor = [UIColor redColor];
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
you need to change you logic for done those things. First you need to declare string Wrong. Because string only hold a single value. You need to declare variable as Dictionary [IndexPath:String] Or AnyHashable Dictionary for store the value. I will give reference code below feel free to refer and if any doubt in the code please ask me in command
Reference Code
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var commend: [IndexPath: String] = [:]
}
extension FirstViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ListTableViewCell.self), for: indexPath) as! ListTableViewCell
cell.button.setTitle(commend[indexPath] ?? "Add commend", for: .normal)
cell.label.text = "\(indexPath.row)"
cell.button.addTarget(self, action: #selector(self.addCommentsAction(_:)), for: .touchUpInside)
return cell
}
#objc func addCommentsAction(_ sender: UIButton) {
guard let nextVC = UIStoryboard(name: "Main", bundle: .some(.main)).instantiateViewController(withIdentifier: String(describing: CommendViewController.self)) as? CommendViewController else { return }
let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to: self.tableView)
guard let indexPath = self.tableView.indexPathForRow(at: buttonPosition) else{
return
}
nextVC.delegate = self
nextVC.indexPath = indexPath
self.navigationController?.pushViewController(nextVC, animated: true)
}
}
extension FirstViewController: DataPassingDelegate{
func commendForIndex(_ string: String, indexPath: IndexPath) {
self.commend[indexPath] = string
self.tableView.reloadData()
}
}
class ListTableViewCell: UITableViewCell{
#IBOutlet weak var label: UILabel!
#IBOutlet weak var button: UIButton!
}
protocol DataPassingDelegate: AnyObject {
func commendForIndex(_ string: String, indexPath: IndexPath)
}
class CommendViewController: UIViewController {
#IBOutlet weak var textView: UITextView!
weak var delegate: DataPassingDelegate?
var indexPath = IndexPath()
#IBAction func doneCommend(_ sender: UIButton){
self.delegate?.commendForIndex(textView.text, indexPath: indexPath)
self.navigationController?.popViewController(animated: true)
}
}

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
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))")
}
}
}
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)
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
Simple 3 step process...!!
Define Model Class
Prepare tableView Cell & handle actions
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
}
}
Create basic tableView and configure dataSource functions
Create tableView cell with two buttons
Create cell class with buttons outlets and actions
Result of this code
Enjoy!

Is there a way to get the value from a text filed in a table view cell to use it in another table view cell?

I'm building an iOS e-commerce app which sells shoe products. This question is about the Checkout screen which is a UITableViewController to collect billing information of the user and save it in Firebase.
Below UITableViewController contains two custom UITableView cells. The first cell contains some text fields to get billing information(Email, Card Number, Expiration Date and CVC) from the user, while the second cell below that contains a submit button to save them in Firebase.
My requirement is to get the billing information from the user and save it in Firebase when clicking the Submit button. (Text fields and submit button are in two separate UITableView cells)
Could you please help me with this. Please find below code snippets.
CheckoutViewController.swift
class CheckoutTableViewController: UITableViewController {
// MARK: - Properties
var shoes : [Shoe]! {
didSet {
tableView.reloadData()
}
}
// MARK: - Structs
struct Storyboard {
static let billingInfoCell = "billingInfoCell"
static let submitButtonCell = "submitButtonCell"
}
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: Storyboard.billingInfoCell, for: indexPath) as! BillingInfoTableViewCell // Contains billing information text fields
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: Storyboard.submitButtonCell, for: indexPath) as! SubmitButtonTableViewCell // Contains Submit button
return cell
} else {
return UITableViewCell()
}
}
}
BillingInfoTableViewCell.swift
class BillingInfoTableViewCell: UITableViewCell {
// MARK: - IBOutlets
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var cardNumberTextField: UITextField!
#IBOutlet weak var expirationDataTextField: UITextField!
#IBOutlet weak var securityNumberTextField: UITextField!
}
SubmitButtonTableViewCell.swift
class SubmitButtonTableViewCell: UITableViewCell {
// MARK: - IBActions
#IBAction func submitOrderButtonTapped(_ sender: UIButton) {
print("Submit button tapped!")
}
}
Please follow the below steps.
Make the outlet of UITableView
#IBOutlet weak var tableView: UITableView!
Make static UITableviewCell
lazy var cellBillingInfo = tableView.dequeueReusableCell(withIdentifier: Storyboard.billingInfoCell) as! BillingInfoTableViewCell
lazy var cellSubmit = tableView.dequeueReusableCell(withIdentifier: Storyboard.submitButtonCell) as! SubmitButtonTableViewCell
Add target for submit button as below.
cellSubmit.btnSumit.addTarget(self, action: #selector(submitOrderButtonTapped(_:).tou), for: .touchUpInside)
Define submit button method
#objc func submitOrderButtonTapped(_ sender: UIButton) {
print(cellBillingInfo.emailTextField.text)
print(cellBillingInfo.cardNumberTextField.text)
print(cellBillingInfo.expirationDataTextField.text)
print(cellBillingInfo.securityNumberTextField.text)
}
Final Code:
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
// MARK: - Properties
lazy var cellBillingInfo = tableView.dequeueReusableCell(withIdentifier: Storyboard.billingInfoCell) as! BillingInfoTableViewCell
lazy var cellSubmit = tableView.dequeueReusableCell(withIdentifier: Storyboard.submitButtonCell) as! SubmitButtonTableViewCell
var shoes : [Shoe]! {
didSet {
tableView.reloadData()
}
}
// MARK: - Structs
struct Storyboard {
static let billingInfoCell = "billingInfoCell"
static let submitButtonCell = "submitButtonCell"
}
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Data source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
return cellBillingInfo
} else if indexPath.row == 1 {
cellSubmit.btnSumit.addTarget(self, action: #selector(submitOrderButtonTapped(_:).tou), for: .touchUpInside)
return cellSubmit
} else {
return UITableViewCell()
}
}
#objc func submitOrderButtonTapped(_ sender: UIButton) {
print(cellBillingInfo.emailTextField.text)
print(cellBillingInfo.cardNumberTextField.text)
print(cellBillingInfo.expirationDataTextField.text)
print(cellBillingInfo.securityNumberTextField.text)
}
}
class SubmitButtonTableViewCell: UITableViewCell {
#IBOutlet weak var btnSumit: UIButton!
}

How can i stop my tableView cell from reusing the button inside it?

I have a function inside a protocol that takes a TableViewcell as an argument.
protocol GoingButtonDelegate {
func goingButtonPressed(cell: TableViewCell)
}
class TableViewCell: UITableViewCell {
// Outlets
#IBOutlet weak var goingButton: UIButton!
var delegate: GoingButtonDelegate?
#IBAction func goingButtonTapped(_ sender: Any) {
delegate?.goingButtonPressed(cell: self)
}
I then go over to my ViewController and implement the delegate and it's function, which is to change the image of a button when tapped. The "goingSelected" is a green image and the "goingDeselected" is a red image.
This all works out fine, when tapped the button of a cell goes from red to green and vice versa. However, when the cell gets reused, the button state of the cell persists and gets reused for the new row that enters view. Is there any way to stop this from happening?
extension ViewController: GoingButtonDelegate {
func goingButtonPressed(cell: TableViewCell) {
cell.goingButton.isSelected = !cell.goingButton.isSelected
if cell.goingButton.isSelected == true {
cell.goingButton.setImage(UIImage(named: "goingSelected"), for: UIControlState.selected)
} else if cell.goingButton.isSelected == false {
cell.goingButton.setImage(UIImage(named: "goingDeselected"), for: UIControlState.normal)
}
}
}
It's possible
just replace
let cell = tableView.dequeueReusableCell(withIdentifier: identifier,
for: indexPath)
with:
let cell= Bundle.main.loadNibNamed(identifier, owner: self, options: nil)?[0]
but I think you need to change your app logic.
Set Images inside of your cell class
class TableViewCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
self.goingButton.setImage(UIImage(named: "goingDeselected"), for:.normal)
self.goingButton.setImage(UIImage(named: "goingSelected"), for:.selected)
}
}
and in method goingButtonPressed(cell: TableViewCell) change cell to your object
and just set Bool type true or false
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.goingButton.isSelected = object.isSelected
...
}
You need to store the selected rows in an array of index paths, before that I think you should make few enhancements ... or a lot!!
the cell itself should handle it's button, the controller should just keep track of all cells status.
Add these two properties to your cell
class TableViewCell: UITableViewCell {
var indexPath:IndexPath?
var isSelected : Bool = false {
didSet{
if isSelected {
cell.goingButton.setImage(UIImage(named: "goingSelected"), for: UIControlState.normal)
} else {
cell.goingButton.setImage(UIImage(named: "goingDeselected"), for: UIControlState.normal)
}
}
}
// Outlets
#IBOutlet weak var goingButton: UIButton!
var delegate: GoingButtonDelegate?
#IBAction func goingButtonTapped(_ sender: Any) {
self.isSelected = !self.isSelected
delegate?.goingButtonPressed(cell: self)
}
..
...
}
And store the selected cells in your view controller to keep track of each cell status.
extension ViewController: GoingButtonDelegate {
var selectedCells = NSMutableArray()
func goingButtonPressed(cell: TableViewCell) {
if cell.isSelected {
selectedCells.add(cell.indexPath)
} else {
selectedCells.remove(cell.indexPath)
}
}
}
and in your "cell for row" method just add a small change
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "yourCellIdentifier") as! TableViewCell
cell.indexPath = indexPath
cell.isSelected = selectedCells.contains(indexPath)
..
...
return cell
}

Switches in Tableviews

I have the following custom UITableViewCell:
I want my view controller to be notified when somebody flips a cell's switch in order to update my model. I've tried using the table view's delegate methods (didSelect, didFinishEditing, didHighlight, etc.) but none of them are called upon this action. Is there any way to do what I want to do? Somebody please help.
actually your UISwitch has added to accessoryView of UITableViewCell, so do like on cellforRowAtIndex
var switchView = UISwitch(frame: CGRect.zero)
aCell.accessoryView = switchView
lightSwitch.tag = indexPath.row
switchView.setOn(false, animated: false)
switchView.addTarget(self, action: #selector(switchChanged(_:), for: .valueChanged)
and get the action of UISwitch as
func switchChanged(_ sender: UISwitch) {
print("which switch is \(sender.tag)")
print("The switch is \(sender?.on ? "ON" : "OFF")")
}
To update your model when somebody flips a cell's switch you need:
Assign cell's #IBAction func onSwitched(_ sender: UISwitch) as UISwitch Value Changed listener as shown on this screenshot
Attach color model to cell
cell.myColorModel = myColorModels[indexPath.row]
In #IBAction func onSwitched(_ sender: UISwitch) simply change selected property in model
#IBAction func onSwitched(_ sender: UISwitch) {
myColorModel.selected = sender.isOn
}
FULL SOURCE CODE
class MyColorModel {
var title: String!
var color: UIColor!
var selected: Bool = false
init(title: String, color: UIColor) {
self.title = title
self.color = color
}
}
class MyColorCell: UITableViewCell {
#IBOutlet weak var colorTitle: UILabel!
#IBOutlet weak var colorImage: UIImageView!
#IBOutlet weak var colorSwitch: UISwitch!
var myColorModel: MyColorModel! {
didSet {
colorTitle.text = myColorModel.title
colorImage.backgroundColor = myColorModel.color
colorSwitch.isOn = myColorModel.selected
}
}
#IBAction func onSwitched(_ sender: UISwitch) {
myColorModel.selected = sender.isOn
}
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
fileprivate var myColorModels = [MyColorModel(title: "Red", color: UIColor.red),
MyColorModel(title: "Green", color: UIColor.green),
MyColorModel(title: "Blue", color: UIColor.blue)]
#IBAction func onColorsCheck(_ sender: AnyObject) {
for myColorModel in myColorModels {
print("color \(myColorModel.title) \((myColorModel.selected) ? "is checked":"is not checked")")
}
}
// MARK: - UITableView datasource & delegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myColorModels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyColorCell") as! MyColorCell
cell.myColorModel = myColorModels[indexPath.row]
return cell
}
}

Resources