I'm trying to use a delegate method to get data from custom cell button press into an array in ViewController.
The button works well, if let works well but data is not transferring from custom cell button press to ViewController array like I want it to...
I'm pretty new to coding still so I know I'm doing something wrong that's obvious. I'm applying the following from SO:
Getting Textfield Values from Custom Table View Cell
How to get user input from UItextfield and add it to an array?
My Custom cell:
import UIKit
class AddEntrantCell: UITableViewCell, UITextFieldDelegate {
var entrantName: ((String) -> Void)?
var entrantCompany: ((String) -> Void)?
@IBOutlet weak var entrantNameTextField: UITextField!
@IBOutlet weak var entrantCompanyTextField: UITextField!
@IBOutlet weak var addEntrant: UIButton!
var delegate: CellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
entrantNameTextField.delegate = self
entrantCompanyTextField.delegate = self
if Global.uiMode == true {
overrideUserInterfaceStyle = .light
} else {
overrideUserInterfaceStyle = .dark
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
// Button press
@IBAction func addEntrantButton(_ sender: UIButton) {
if let name = entrantNameTextField.text, let company = entrantCompanyTextField.text {
delegate?.addEntrants(name: name, company: company)
}
}
}
My VC with the tableView:
import UIKit
protocol CellDelegate {
func addEntrants(name: String, company: String)
}
class EntrySec: UIViewController, CellDelegate {
@IBOutlet weak var spaceStatus: UIButton!
@IBOutlet weak var entrantsTable: UITableView!
var entryGrid: [Entrant] = [
Entrant(name: "", company: ""),
Entrant(name: "Bob Lob", company: "Blue"),
Entrant(name: "John Lon", company: "Red")
]
override func viewDidLoad() {
super.viewDidLoad()
entrantsTable.dataSource = self
entrantsTable.register(UINib(nibName: Global.headerCellNibName, bundle: nil), forCellReuseIdentifier: Global.headerCellIdentifier)
entrantsTable.register(UINib(nibName: Global.bodyCellNibName, bundle: nil), forCellReuseIdentifier: Global.bodyCellIdentifier)
if Global.uiMode == true {
overrideUserInterfaceStyle = .light
} else {
overrideUserInterfaceStyle = .dark
}
}
func addEntrants(name: String, company: String) {
entryGrid.append(Entrant(name: name, company: company)) // This does not work
print("\(name) \(company)") // This does not work
}
@IBAction func pauseSession(_ sender: UIButton) {
}
@IBAction func closeSession(_ sender: UIButton) {
}
@IBAction func menu(_ sender: UIButton) {
}
}
extension EntrySession: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return entryGrid.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let addEntrantCell = entrantsTable.dequeueReusableCell(withIdentifier: Global.headerCellIdentifier, for: indexPath) as! AddEntrantCell
addEntrantCell.entrantNameTextField.text = entryGrid[indexPath.row].name
addEntrantCell.entrantCompanyTextField.text = entryGrid[indexPath.row].company
return addEntrantCell
} else {
let entrantCell = entrantsTable.dequeueReusableCell(withIdentifier: Global.bodyCellIdentifier, for: indexPath) as! EntrantCell
entrantCell.textLabel?.text = entryGrid[indexPath.row].name
if entrantCell.textLabel?.text == "" {
entrantCell.backgroundColor = #colorLiteral(red: 0.9764705882, green: 0.4274509804, blue: 0, alpha: 1)
entrantCell.alpha = 0.5
}
return entrantCell
}
}
}
You have not set cell delegate inside the cellForRowAt
. so you have to set CellDelegate
inside the cellForRowAt
method. Like this.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let addEntrantCell = entrantsTable.dequeueReusableCell(withIdentifier: Global.headerCellIdentifier, for: indexPath) as! AddEntrantCell
addEntrantCell.delegate = self // <--- Add delegate here
addEntrantCell.entrantNameTextField.text = entryGrid[indexPath.row].name
addEntrantCell.entrantCompanyTextField.text = entryGrid[indexPath.row].company
return addEntrantCell
} else {
let entrantCell = entrantsTable.dequeueReusableCell(withIdentifier: Global.bodyCellIdentifier, for: indexPath) as! EntrantCell
entrantCell.textLabel?.text = entryGrid[indexPath.row].name
if entrantCell.textLabel?.text == "" {
entrantCell.backgroundColor = #colorLiteral(red: 0.9764705882, green: 0.4274509804, blue: 0, alpha: 1)
entrantCell.alpha = 0.5
}
return entrantCell
}
}
You can also use a closure instead of a delegate. (You have already added code but need some correction)
Update your cell class with this and remove other closures.
var entrants: ((String, String) -> Void)?
@IBAction func addEntrantButton(_ sender: UIButton) {
if let name = entrantNameTextField.text, let company = entrantCompanyTextField.text {
entrants?(name, company)
}
}
and inside the cellForRow
method, instead of set delegate add this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let addEntrantCell = entrantsTable.dequeueReusableCell(withIdentifier: Global.headerCellIdentifier, for: indexPath) as! AddEntrantCell
addEntrantCell.entrants = { name, company in
entryGrid.append(Entrant(name: name, company: company))
} // <--- Here
// Rest of the code here