how to enable button when all textfields filled in tableviewcell(SWIFT) - ios

I want to enable the button in the viewcontroller when I fill in the textfield in the tableviewcell.
I don't know how to solve the problem.
Sorry. I am immature in English.
button(viewController) isEnable = false
fill textfields(inside tableviewcell)
button(viewController) isEnable = true
1. ViewController
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
#IBOutlet var tableView: UITableView!
#IBOutlet var viewLabel: UILabel!
#IBOutlet var clickBtn: UIButton!
var cell: CustomTableViewCell!
override func viewDidLoad() {
super.viewDidLoad()
self.clickBtn.isEnabled = false
cell.textFieldCell.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
cell.textFieldCell2.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
}
#objc func editingChanged(sender: UITextField) {
sender.text = sender.text?.trimmingCharacters(in: .whitespaces)
guard
let text1 = cell.textFieldCell.text, !text1.isEmpty,
let text2 = cell.textFieldCell2.text, !text2.isEmpty
else
{
self.clickBtn.isEnabled = false
return
}
clickBtn.isEnabled = true
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! CustomTableViewCell
return cell
}
}
2. CustomTableView
import UIKit
class CustomTableViewCell: UITableViewCell, UITextFieldDelegate {
#IBOutlet var myLabel: UILabel!
#IBOutlet var textFieldCell: UITextField!
#IBOutlet var textFieldCell2: UITextField!
}

As the table view contains only one cell why do you use a table view at all?
And if you really need to use a table view why don't you use a static cell?
A simple solution is to move the target/action code from viewDidLoad into the didSet property observer of the cell
var cell: CustomTableViewCell! {
didSet {
cell.textFieldCell.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
cell.textFieldCell2.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.clickBtn.isEnabled = false
}

One option is to use delegate.
protocol CustomTableViewCellDelegate {
func editingChanged(_ String: yourString)
}
In table view cell
class TableViewCell: UITaleViewCell {
// declare the delegate
var delegate: CustomTableViewCellDelegate?
// and pass it like this from where you want to pass
delegate?.editingChanged(cookie)
}
For using in tableViewController. first assign the delegate to self in cell for row at indexpath method. Then implement the delegate in it.
extension CustomTableViewController: CustomTableViewCellDelegate {
func editingChanged(String: yourString) {
// use it accordingly
}
}

Related

Is there a simple way to delete specific custom cells from a UITableView?

I am trying to instantiate empty Buyer cells (custom cell) in my table view and then have the user populate the buyers' names. When the user presses the delete button for a row/cell, it should delete the corresponding row/cell regardless of whether or not the textfield for that row has been populated or not. Clearly, I am not getting the desired behavior. For example, when I press delete Row0 (whose textfield says "Buyer 0") and the tableview reloads, Buyer 0 is still there, but one of the empty Buyer cells at the end gets deleted instead.
import UIKit
class EntryAlertViewController: UIViewController {
//Fields/Table
#IBOutlet weak var itemField: UITextField!
#IBOutlet weak var priceField: UITextField!
#IBOutlet weak var tableView: UITableView!
//Visual Components
#IBOutlet weak var mainView: UIView!
#IBOutlet weak var titleView: UIView!
#IBOutlet weak var splitItemButton: UIButton!
#IBOutlet weak var cancelButton: UIButton!
#IBOutlet weak var addItemButton: UIButton!
//Commonly Used Objects/Variables
var potentialBuyers: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
potentialBuyers.append("")
tableView.dataSource = self
tableView.register(UINib(nibName: "BuyerCell", bundle: nil), forCellReuseIdentifier: "ReusableCell")
}
override func viewWillAppear(_ animated: Bool) {
}
#IBAction func splitItemPressed(_ sender: UIButton) {
potentialBuyers.append("")
tableView.reloadData()
}
}
Here are the tableview datasource and the delete button delegate.
extension EntryAlertViewController: UITableViewDataSource, DeleteButtonDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return potentialBuyers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! BuyerCell
cell.deleteButtonDelegate = self
cell.indexPath = indexPath
cell.nameField.text = cell.buyerName
if potentialBuyers.count == 1 {
cell.deleteButton.isHidden = true
} else {
cell.deleteButton.isHidden = false
}
return cell
}
func deletePressed(index: Int) {
potentialBuyers.remove(at: index)
tableView.reloadData()
}
}
And here is my BuyerCell class with the UITextFieldDelegate as an extension.
import UIKit
protocol DeleteButtonDelegate {
func deletePressed(index: Int)
}
class BuyerCell: UITableViewCell {
#IBOutlet weak var deleteButton: UIButton!
#IBOutlet weak var nameField: UITextField!
var deleteButtonDelegate: DeleteButtonDelegate!
var indexPath: IndexPath!
var buyerName: String?
override func awakeFromNib() {
super.awakeFromNib()
self.nameField.delegate = self
}
#IBAction func deletePressed(_ sender: UIButton) {
//print the indexPath.row that this was pressed for
print("delet pressed for \(indexPath.row)")
self.deleteButtonDelegate?.deletePressed(index: indexPath.row)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension BuyerCell: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
print("textFieldDidBeginEditing")
buyerName = nameField.text
}
func textFieldDidEndEditing(_ textField: UITextField) {
print("textFieldDidEndEditing")
buyerName = nameField.text
}
}
Your problem is in this line
cell.nameField.text = cell.buyerName
Cells are reused from a reuse pool, so you can't rely on the cell holding any particular state or value.
Your buyer name needs to come from your data model array.
Something like
cell.nameField.text = self.potentialBuyers[indexPath.row]
Reloading the whole tableview is a bit excessive when you have only deleted a single row; Just delete the relevant row.
You can also clean up your delegation protocol so that there is no need for the cell to track its indexPath -
protocol DeleteButtonDelegate {
func deletePressed(in cell: UITableViewCell)
}
In your cell:
#IBAction func deletePressed(_ sender: UIButton) {
self.deleteButtonDelegate?.deletePressed(in: self)
}
In your view controller:
func deletePressed(in cell: UITableViewCell) {
guard let indexPath = tableView.indexPath(for: cell) else {
return
}
potentialBuyers.remove(at: indexPath.row)
tableView.deleteRows(at:[indexPath], with: .automatic)
}
There is a major issue in your code. You are not updating the data model so the changes in the cells are lost when the user scrolls.
Rather then quite objective-c-ish protocol/delegate in Swift callback closures are much more convenient and efficient. You can use one callback for both updating the model and deleting the cell.
Replace the BuyerCell cell with
class BuyerCell: UITableViewCell {
#IBOutlet weak var deleteButton: UIButton!
#IBOutlet weak var nameField: UITextField!
var callback : ((UITableViewCell, String?) -> Void)?
override func awakeFromNib() {
super.awakeFromNib()
self.nameField.delegate = self
}
#IBAction func deletePressed(_ sender: UIButton) {
callback?(self, nil)
}
}
extension BuyerCell: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
print("textFieldDidBeginEditing")
callback?(self, nameField.text)
}
func textFieldDidEndEditing(_ textField: UITextField) {
print("textFieldDidEndEditing")
callback?(self, nameField.text)
}
}
In the controller in cellForRow assign the callback and handle the actions. The actions work also reliably if cells are reordered, inserted or deleted.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReusableCell", for: indexPath) as! BuyerCell
let buyerName = potentialBuyers[indexPath.row]
cell.nameField.text = buyerName
cell.callback = { [unowned self] cCell, cName in
let currentIndexPath = tableView.indexPath(for: cCell)!
if let name = cName {
self.potentialBuyers[currentIndexPath.row] = name
} else {
self.potentialBuyers.remove(at: currentIndexPath.row)
tableView.deleteRows(at: [currentIndexPath], with: .fade)
}
}
cell.deleteButton.isHidden = potentialBuyers.count == 1
return cell
}

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!
}

Deleting a UITableView cell in a specific section

There is a task. Each cell contains a button by clicking which you want to delete this cell. The problem is that sections are used to delineate the entire list by category. The data I take from Realm DB. removal must occur under two conditions because the name is repeated, so you need to consider the name from the label and the name of the section. I will be very grateful for the sample code with comments.
import UIKit
import RealmSwift
class PurchesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var purchesTableView: UITableView!
let manage = ManagerData()
override func viewDidLoad() {
super.viewDidLoad()
purchesTableView.delegate = self
purchesTableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
purchesTableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return manage.loadPurchases().0.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return manage.loadPurchases().0[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return manage.loadPurchases().1[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "purchesCell", for: indexPath) as! CustomPurchesTableViewCell
cell.productLabel.text = manage.loadPurchases().1[indexPath.section][indexPath.row]
cell.weightProductLabel.text = manage.loadPurchases().2[indexPath.section][indexPath.row]
cell.weightNameLabel.text = manage.loadPurchases().3[indexPath.section][indexPath.row]
// cell.boughtButton.addTarget(self, action: #selector(removeProduct), for: .touchUpInside)
return cell
}
}
class CustomPurchesTableViewCell: UITableViewCell {
#IBOutlet weak var boughtButton: UIButton!
#IBOutlet weak var productLabel: UILabel!
#IBOutlet weak var weightProductLabel: UILabel!
#IBOutlet weak var weightNameLabel: UILabel!
#IBAction func removePurches(_ sender: Any) {
print("remove")
}
}
method for get data
func loadPurchases() -> ([String], Array<Array<String>>, Array<Array<String>>, Array<Array<String>>) {
var sections: [String] = []
var product = Array<Array<String>>()
var weight = Array<Array<String>>()
var nameWeight = Array<Array<String>>()
let realm = try! Realm()
let data = realm.objects(Purches.self)
for item in data {
if sections.contains(item.nameDish) == false {
sections.append(item.nameDish)
}
}
for a in sections {
var productArr = Array<String>()
var weightArr = Array<String>()
var nameWeightArr = Array<String>()
for prod in data {
if a == prod.nameDish {
productArr.append(prod.product)
weightArr.append(prod.weight)
nameWeightArr.append(prod.nameWeigh)
}
}
product.append(productArr)
weight.append(weightArr)
nameWeight.append(nameWeightArr)
}
return (sections, product, weight, nameWeight)
}
Index path you will get in cell class
Index path have two property section and row for table view
Now you can create on more method in Controller class and assign to a variable to every cell or you can use editAction provided by table view for delete
in order to get number section and row you need create IBOutlet in custom cell and on ViewController class is created addTarget for your button.
Example code at the bottom.
import UIKit
import RealmSwift
class PurchesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var purchesTableView: UITableView!
let manage = ManagerData()
//... more code ...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "purchesCell", for: indexPath) as! CustomPurchesTableViewCell
cell.productLabel.text = manage.loadPurchases().1[indexPath.section][indexPath.row]
cell.weightProductLabel.text = manage.loadPurchases().2[indexPath.section][indexPath.row]
cell.weightNameLabel.text = manage.loadPurchases().3[indexPath.section][indexPath.row]
cell.boughtButton.addTarget(self, action: #selector(removePurches(_:)), for: .touchUpInside)
return cell
}
#objc func removePurches(_ sender: UIButton) {
let position: CGPoint = sender.convert(CGPoint.zero, to: purchesTableView)
let indexPath: IndexPath! = self.purchesTableView.indexPathForRow(at: position)
print("indexPath.row is = \(indexPath.row) && indexPath.section is = \(indexPath.section)")
purchesTableView.deleteRows(at: [indexPath], with: .fade)
}
}
and custom class CustomPurchesTableViewCell for cell
class CustomPurchesTableViewCell: UITableViewCell {
#IBOutlet weak var boughtButton: UIButton! // you button for press
#IBOutlet weak var productLabel: UILabel!
#IBOutlet weak var weightProductLabel: UILabel!
#IBOutlet weak var weightNameLabel: UILabel!
}

Get data from all UITableViewCells separately

I have a TableViewController that returns four cells. Each cell has three buttons in it. The cells themselves don't have any interaction or segues attached because I don't need the user to interact with the cells, just the three buttons in the cells.
I have an empty array called selections and if each button is pressed I want to append an item to that array. So far I can't find any method that will keep track of each button that's pressed.
What method can I put this code in?
if cell.yes.isSelected == true {
firstChoice = 1
selections.append(firstChoice)
print(selections.count, selections.reduce(0, +))
}
Such that it will work for ALL of the cells loaded by my TableViewController?
In order to achieve what you want you need to create delegates for both the custom cell and button.
//here is the view controller class
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, CustomCellDelegate {
var firstChoice = 0
var selections = Array<Any>()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as? CustomCell
cell?.delegate = self
return cell!
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func cellButtonTapped(_ cell: CustomCell) {
if cell.isSelected {
firstChoice = 1
selections.append(firstChoice)
}
}
}
The custom cell class
protocol CustomCellDelegate {
func cellButtonTapped(_ cell: CustomCell)
}
class CustomCell: UITableViewCell, CustomButtonDelegate {
var delegate: CustomCellDelegate?
#IBOutlet weak var button1: CustomButton!
#IBOutlet weak var button2: CustomButton!
#IBOutlet weak var button3: CustomButton!
override func awakeFromNib() {
super.awakeFromNib()
button1.delegate = self
button2.delegate = self
button3.delegate = self
}
func buttonTapped() {
self.isSelected = !self.isSelected
if let delegate = delegate {
delegate.cellButtonTapped(self)
}
}
}
And the custom button
protocol CustomButtonDelegate{
func buttonTapped()
}
class CustomButton: UIButton {
var delegate: CustomButtonDelegate?
override func awakeFromNib() {
super.awakeFromNib()
self.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
}
func buttonTapped(_ sender: AnyObject) {
if let delegate = delegate {
delegate.buttonTapped()
}
}
}
Both of them with their protocols
First of all - you should keep information about pressed button in your ViewController - not inside the table cells.
Table cells will be reused - and you will lose that information.
Best way to do that will be to use a custom delegate between cells and TableViewController. While creating each cell, you make:
cell.delegate = self
and inside a cell when the buttons are pressed, you call this delegate methods - let's say didPressButton1 didPressButton2.
Also if you want to have this state to be persistent (for example to disable, enable some button) while creating cells in your TableViewController you need to pull existing data and apply it to the cell itself - again TableViewCells are reused.
I don't know your specification, but it seems you could add a different target to each button:
button1?.addTarget(self, action:#selector(self.button1Clicked), forControlEvents: .TouchUpInside)
...
button3?.addTarget(self, action:#selector(self.button3Clicked), forControlEvents: .TouchUpInside)
and then you could have:
func button1Clicked() {
firstChoice = 1
selections.append(firstChoice)
}
...
func button3Clicked() {
firstChoice = 3
selections.append(firstChoice)
}
This way if button number 1 get clicked, button1Clicked() is fired and you can do your work as intended.

Update model through UIButton within a UITableViewCell

In MainVC.swift I'm capturing the tag of my custom "PlayerCell". I want to press theincreaseBtn (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?
}
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

Resources