1.Create a subclass named EmpTVCell
Cmd+N > Cocoa Touch Class > select UITableViewCell
class EmpTVCell: UITableViewCell {
@IBOutlet weak var labelEmpName: UILabel!
@IBOutlet weak var labelEmpTeam: UILabel!
// type function
// you can assign a function expression to the variable
// empty block by default. we will implement this in main class
var transferEmployee: (() -> ()) = {}
// whenever user presses the button -> call this function
@IBAction func transferEmployee(_ sender: Any) {
transferEmployee()
}
}
*NOTE: if you want to see the storyboard on the side, click button below +
2.Assign identifier
to the prototype cell, empCell
3.Change class name to EmpTVCell
we created earlier
4.Connect the UITableView with datasource and delegate
class ViewController: UIViewController {
@IBOutlet weak var employeeTableView: UITableView!
var employees: [Employee] = [
Employee(name: "John", team: "Frontend"),
Employee(name: "Jane", team: "Backend"),
Employee(name: "Mike", team: "Product"),
Employee(name: "Sarah", team: "Design"),
Employee(name: "Tom", team: "Testing")
]
override func viewDidLoad() {
super.viewDidLoad()
employeeTableView.dataSource = self
employeeTableView.delegate = self
}
}
In this step, we can create an extension and add both UITableViewDataSource, UITableViewDelegate
in the extension itself as below.
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return employees.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// custom ui table view cell
// you have to let class know that this is the custome class of ui table view cell!
// so you have to specify custom subclass of ui table view cell
// without type casting to EmpTVcell -> it will be treated as normal ui table view cell
let cell = tableView.dequeueReusableCell(withIdentifier: "empCell", for: indexPath) as! EmpTVCell
// now you can call labelEmpName and Team of subclass of ui table view cell = EmpTVCell because of the type casting above
cell.labelEmpName.text = employees[indexPath.row].name
cell.labelEmpTeam.text = employees[indexPath.row].team
// now I can now provide a new block!
// this is a button press event happened from another subclass (EmpTVCell subclass)
// closure = implement between two classes
cell.transferEmployee = {
// transfer logic here
print("Hello, \(self.employees[indexPath.row].name)")
self.changeTeam(for: indexPath.row) {
// reload table view for updating the rows again! it still won't work if we don't have completion handler
// this will happen even before user enters an input
// we only reload table after we have updated a team in the data source
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 86
}
}
*NOTE: anything you do here is treated like you did to main class itself
5.Implement a button click handler (transferEmployee - empty in the subclass, EmpTVCell
)
class ViewController: UIViewController {
...
func changeTeam(for index: Int, completion: @escaping (() -> Void)) {
// create an alert = async, we need to wait till the action is completed before relaoading tabie View rows
// @escaping is used to inform callers of a function that takes a closure
// that the closure might be stored or otherwise outlive the scope of the receiving function.
let alert = UIAlertController(title: "Team Transfer", message: "Select the team you want to transfer to", preferredStyle: .actionSheet)
// enum Team
for team in Team.allCases {
// create an action
let action = UIAlertAction(title: team.rawValue, style: .default) { _ in
self.employees[index].team = team.rawValue // Frontend, Backend, Product...
// add completion handler after I have updated data source
completion() // invoke our own completion handler -> reloadRows
}
// add it to the alert
alert.addAction(action)
}
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
// present this alert
present(alert, animated: true)
}
}
Demo
Top comments (0)