Hey Brian, I really need help implementing how to delete employees from the tableview section and coredata. I keep getting a crash that says
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (0) must be equal to the number of sections contained in the table view before the update (4), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).'
*** First throw call stack:
Here is my EmployeeController code...
import UIKit
import CoreData
// lets create a UILabel subclass for custom text drawing
class IndentedLabel: UILabel {
}
class EmployeesController: UITableViewController, CreateEmployeeControllerDelegate {
func didAddEmployee(employee: Employee) {
guard let section = employeeTypes.index(of: employee.type!) else { return }
// what is my row?
let row = allEmployees[section].count
let insertionIndexPath = IndexPath(row: row, section: section)
allEmployees[section].append(employee)
tableView.insertRows(at: [insertionIndexPath], with: .middle)
}
func didEditEmployee(employee: Employee) {
// update my tableview somehow
guard let section = employeeTypes.index(of: employee.type!) else { return }
let row = allEmployees[section].count
allEmployees[section].append(employee)
let reloadIndexPath = IndexPath(row: row, section: 4)
tableView.reloadRows(at: [reloadIndexPath], with: .middle)
}
var company: Company?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationItem.title = company?.name
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let label = IndentedLabel()
if section == 0 {
label.text = EmployeeType.Intern.rawValue
} else if section == 1 {
label.text = EmployeeType.Executive.rawValue
} else {
label.text = EmployeeType.SeniorManagement.rawValue
}
label.text = employeeTypes[section]
label.backgroundColor = UIColor.white
label.textColor = UIColor.darkBlue
label.font = UIFont.boldSystemFont(ofSize: 16)
return label
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
var allEmployees = [[Employee]]()
var employeeTypes = [
EmployeeType.Intern.rawValue,
EmployeeType.Executive.rawValue,
EmployeeType.SeniorManagement.rawValue,
EmployeeType.Staff.rawValue,
]
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete") { (_,indexPath) in
self.allEmployees = [self.allEmployees[indexPath.row]]
//let company = self.companies[indexPath.row]
self.allEmployees.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
let editAction = UITableViewRowAction(style: .normal, title: "Edit") { (_,indexPath) in print("Editing company...")
}
return [deleteAction, editAction]
}
private func fetchEmployees() {
guard let companyEmployees = company?.employees?.allObjects
as? [Employee] else { return }
allEmployees = []
// let's use my array and loop to filter instead
employeeTypes.forEach { (employeeType) in
// somehow construct my allEmployees array
allEmployees.append(
companyEmployees.filter { $0.type == employeeType }
)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return allEmployees.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allEmployees[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let employee = allEmployees[indexPath.section][indexPath.row]
cell.textLabel?.text = employee.name
if let birthday = employee.employeeInformation?.birthday {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd, yyyy"
cell.textLabel?.text = "\(employee.name ?? "") \(dateFormatter.string(from: birthday))"
}
cell.backgroundColor = UIColor.tealColor
cell.textLabel?.textColor = .white
cell.textLabel?.font = UIFont.boldSystemFont(ofSize: 15)
return cell
}
let cellId = "cellllllllllllId"
override func viewDidLoad() {
super.viewDidLoad()
fetchEmployees()
tableView.backgroundColor = UIColor.darkBlue
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
setupPlusButtonInNavBar(selector: #selector(handleAdd))
}
@objc private func handleAdd() {
print("Trying to add an employee..")
let createEmployeeController = CreateEmployeeController()
createEmployeeController.delegate = self
createEmployeeController.company = company
let navController = UINavigationController(rootViewController: createEmployeeController)
present(navController, animated: true, completion: nil)
}
@objc private func handleEdit() {
print("Trying to add an employee..")
let createEmployeeController = CreateEmployeeController()
createEmployeeController.delegate = self
createEmployeeController.company = company
let navController = UINavigationController(rootViewController: createEmployeeController)
present(navController, animated: true, completion: nil)
}
}