title: Invalid update: invalid number of sections in UITableView
body: <p>I'm not finding an answer to the issue that I'm having. I'm using NSFetchedResultsControllerDelegete to connect my table view with my data. I'm retrieving the data with sectionNameKeyPath set so that I can group items in the table view. If I have only one item in a section of the table view and delete it, then I get the following error:</p>
  
  <blockquote>
    <p>Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (2), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).</p>
  </blockquote>
  
  <p>Here is my screen before the delete:</p>
  
  <p><a href="https://i.stack.imgur.com/pxJ26l.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/pxJ26l.png" alt="enter image description here"></a></p>
  
  <p>Here's my code for the view:</p>
  
  <pre><code>import CoreData
  
  class VehicleTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {
  
      var deleteItemIndexPath: IndexPath? = nil
  
      lazy var dao: DAOUtilities = {
          return DAOUtilities(context: GlobalVariables.getContext())
      }()
  
      lazy var fetchedResultsController: NSFetchedResultsController&lt;Vehicles&gt; = {
          let fetchRequest = NSFetchRequest&lt;NSFetchRequestResult&gt;(entityName: "Vehicles")
  
          fetchRequest.sortDescriptors = [NSSortDescriptor(key: "activeFlag", ascending: false), NSSortDescriptor(key: "vehicleDesc", ascending: true)]
  
          // Initialize Fetched Results Controller
          let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: GlobalVariables.getContext(), sectionNameKeyPath: "activeFlag", cacheName: nil)
  
          // Configure Fetched Results Controller
          fetchedResultsController.delegate = self
  
          return fetchedResultsController as! NSFetchedResultsController&lt;Vehicles&gt;
      }()
  
      override func viewDidLoad() {
          super.viewDidLoad()
      }
  
      override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
  
          do {
              try self.fetchedResultsController.performFetch()
          }
          catch {
              let fetchError = error as NSError
              print("\(fetchError), \(fetchError.userInfo)")
          }
          tableView.reloadData()
      }
  
      // MARK: - Table view data source
  
      override func numberOfSections(in tableView: UITableView) -&gt; Int {
          if let sections = fetchedResultsController.sections {
              return sections.count
          }
  
          return 0
      }
  
      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
          if let sections = fetchedResultsController.sections {
              let sectionInfo = sections[section]
              return sectionInfo.numberOfObjects
          }
  
          return 0
      }
  
      override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -&gt; UIView? {
          let view = UIView()
          view.backgroundColor = UIColor(red: 55/255, green: 120/255, blue: 250/255, alpha: 1)
  
          guard let sectionInfo = fetchedResultsController.sections?[section] else {
              return view
          }
          let title = UILabel()
          title.font = UIFont.boldSystemFont(ofSize: 16)
          title.textColor = .white
          title.text = sectionInfo.name == "1" ? "Active" : "Inactive"
          view.addSubview(title)
          title.translatesAutoresizingMaskIntoConstraints = false
          title.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
          title.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true
  
          return view
      }
  
      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
          let cell = tableView.dequeueReusableCell(withIdentifier: "vehicleCell", for: indexPath)
  
          if indexPath.row % 2 == 0 {
              cell.backgroundColor = UIColor.clear
          }
          else {
              cell.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2)
          }
  
          let vehicle = fetchedResultsController.object(at: indexPath)
          cell.textLabel!.text = vehicle.vehicleDesc
  
          return cell
      }
  
      // Override to support conditional editing of the table view.
      override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -&gt; Bool {
          return true
      }
  
      // Override to support editing the table view.
      override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
          if editingStyle == .delete {
              deleteItemIndexPath = indexPath
              let vehicle = fetchedResultsController.object(at: indexPath)
              confirmDelete(itemToDelete: vehicle.vehicleDesc!)
          }
      }
  
      func confirmDelete(itemToDelete: String) {
          let alert = UIAlertController(title: "Delete Vehicle", message: "Are you sure you want to delete vehicle \(itemToDelete)", preferredStyle: .actionSheet)
          let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: handleDeleteItem)
          let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: cancelDeleteItem)
          alert.addAction(deleteAction)
          alert.addAction(cancelAction)
          self.present(alert, animated: true, completion: nil)
      }
  
      func handleDeleteItem(alertAction: UIAlertAction!) -&gt; Void {
          if let indexPath = deleteItemIndexPath {
              let vehicle = fetchedResultsController.object(at: indexPath)
              let route = dao.getRouteForVehicle(vehicleId: vehicle.vehicleId!)
  
              if let _ = route {
                  vehicle.activeFlag = false
              }
              else {
                  GlobalVariables.getContext().delete(vehicle)
              }
          }
      }
  
      func cancelDeleteItem(alertAction: UIAlertAction!) {
          deleteItemIndexPath = nil
      }
  
      func controllerWillChangeContent(_ controller: NSFetchedResultsController&lt;NSFetchRequestResult&gt;) {
          tableView.beginUpdates()
      }
  
      func controllerDidChangeContent(_ controller: NSFetchedResultsController&lt;NSFetchRequestResult&gt;) {
          tableView.endUpdates()
      }
  
      func controller(_ controller: NSFetchedResultsController&lt;NSFetchRequestResult&gt;, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
          switch (type) {
          case .insert:
              if let indexPath = newIndexPath {
                  tableView.insertRows(at: [indexPath], with: .fade)
              }
              break;
          case .delete:
              if let indexPath = indexPath {
                  tableView.deleteRows(at: [indexPath], with: .fade)
                  tableView.reloadData()
              }
              break;
  //        case .update:
  //            if let indexPath = indexPath {
  //                let cell = tableView.cellForRow(at: indexPath)
  //                configureCell(cell, atIndexPath: indexPath)
  //            }
  //            break;
          case .move:
              if let indexPath = indexPath {
                  tableView.deleteRows(at: [indexPath], with: .fade)
              }
  
              if let newIndexPath = newIndexPath {
                  tableView.insertRows(at: [newIndexPath], with: .fade)
              }
              break;
          default:
              break
          }
      }
  
      // MARK: - segue
  
      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
          if segue.identifier == "editVehicleSegue" {
              if let vehicleEditViewController = segue.destination as? VehicleEditViewController {
                  if let indexPath = tableView.indexPathForSelectedRow {
                      let vehicle = fetchedResultsController.object(at: indexPath)
                      vehicleEditViewController.vehicle = vehicle
                      vehicleEditViewController.tableView = tableView
                  }
              }
          }
      }
  
  //    // MARK: - Actions
  //
  //    @IBAction func btnAdd_ACTION(_ sender: UIBarButtonItem) {
  //        var emptyFound = false
  //        for i in 0..&lt;vehicles.count {
  //            let vehicle = vehicles[i]
  //            if vehicle.isEmpty {
  //                emptyFound = true
  //                break
  //            }
  //        }
  //        if !emptyFound {
  //            vehicles.append("")
  //            tableView.reloadData()
  //        }
  //    }
  }
  </code></pre>