0

I am trying to delete a cell in the tableview from another view controller. I have modeled my code similar to the question posted below but I still can't seem to successfully delete the selected row/cell in the CalorieVC when the delete button is pressed in the DeleteVC

Deleting a row of a tableview from another viewcontroller

SideNote: there is button in the cells to popup the DeleteVC, I am also getting an error upon pressing the the deleteBtn in the CalorieVC: DeleteRowInTableviewDelegate on let picked saying Thread 1: Fatal error: Index out of range

Deleting cell

import UIKit

class CalorieViewController: UIViewController {

    var selectedFood: FoodList!       // allows data to be passed into the CalorieVC
    var deleteItems: CalorieItem?              // passes data to DeleteVC

    // allows data to be sepearted into sections
    var calorieItems: [CalorieItem] = []
    var groupedCalorieItems: [String: [CalorieItem]] = [:]
    var dateSectionTitle: [String] = []

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        tableView.dataSource = self
        tableView.delegate = self

        // Allows data in cells to seperate by section
        groupedCalorieItems = Dictionary(grouping: calorieItems, by: {$0.foodList.date})
        dateSectionTitle = groupedCalorieItems.map{$0.key}.sorted()
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "DeleteSegue" {
        let vc: DeleteViewController = segue.destination as! DeleteViewController
            vc.deleteItems = self.deleteItems
       //     vc.delegate = self

        }
    }
}

extension CalorieViewController: UITableViewDelegate, UITableViewDataSource{

    func numberOfSections(in tableView: UITableView) -> Int {
        return dateSectionTitle.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let date = dateSectionTitle[section]
        return groupedCalorieItems[date]!.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let calorieCell = tableView.dequeueReusableCell(withIdentifier: "CalorieCell") as! CalorieCell

        let date = dateSectionTitle[indexPath.section]
        let caloriesToDisplay = groupedCalorieItems[date]![indexPath.row]
        calorieCell.configure(withCalorieItems: caloriesToDisplay.foodList)

        return calorieCell
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let calorieHeader = tableView.dequeueReusableCell(withIdentifier: "CalorieHeader") as! CalorieHeader

        let headerTitle = dateSectionTitle[section]
        calorieHeader.dateLbl.text = "Date: \(headerTitle)"
        return calorieHeader
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 45
    }

    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let calorieFooter = tableView.dequeueReusableCell(withIdentifier: "CalorieFooter") as! CalorieFooter

        //Cell Total Code
        let date = dateSectionTitle[section]
        let subtotal = groupedCalorieItems[dispensary]?.map { $0.getCalorieTotal() }.reduce(0, +) ?? 0
        calorieFooter.calorieTotal.text = String(subtotal!)

        return calorieFooter
    }

    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 150
    }

}

extension CalorieViewController: DeleteRowInTableviewDelegate {
    func deleteRow(inTableview rowToDelete: Int) {
        let picked = dateSectionTitle[rowToDelete]
        let selectedCell = groupedCalorieItems[dod]
        delete(selectedCell)
      //  calorieItems.remove(at: rowToDelete)  // tried using this and I get an error code upon segueing back to the CalorieVC
        tableView.reloadData()
    }
}

import UIKit

protocol DeleteRowInTableviewDelegate: NSObjectProtocol {
    func deleteRow(inTableview rowToDelete: Int)
}

class DeleteViewController: UIViewController {

    var modifyItems: CartItem!
    var delegate: DeleteRowInTableviewDelegate?

    @IBOutlet weak var deleteLbl: UILabel!  
    @IBOutlet weak var deleteBtn: UIButton!
    @IBOutlet weak var cancelBtn: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        if isMovingFromParent {
            delegate!.deleteRow(inTableview: 1)
        }
        deleteLbl.text = "Are you sure you want to delete this Food Item from your calorie List?"
    }    

    @IBAction func decline(_ sender: Any) {
        dismiss(animated: true)
        delegate!.deleteRow(inTableview: 1)
        print("Delete Item")
    }

    @IBAction func cancel(_ sender: Any) {
        dismiss(animated: true)
        print("Cancel Delete")
    }
}
Evelyn
  • 186
  • 1
  • 4
  • 25

1 Answers1

2
  1. Remove the value from the dataSource
  2. Remove the table cell

    extension CalorieViewController: DeleteRowInTableviewDelegate {
      func deleteRow(inTableview rowToDelete: Int) {
        if caloriesItems.count > rowToDelete {
          calorieItems.remove(at: rowToDelete)
          tableView.deleteRows(at: [IndexPath(row: rowToDelete, section: 0)], with: .automatic)
        } else { 
            print("index not present")
          }
      }
    }
    

Do not call reloadData just to delete one row. This is a bad practice. Use deleteRows instead.

Keshu R.
  • 5,045
  • 1
  • 18
  • 38
  • I just ran it im getting the same error Thread 1: Fatal error: Index out of range on ```calorieItems.remove(at: rowToDelete)``` when pressing the deleteBtn. PS. I didn't down vote your answer – Evelyn Dec 29 '19 at 06:16
  • updated the answer. seems like the index that you are passing is not not present in the caloriesItems. – Keshu R. Dec 29 '19 at 06:20
  • 1
    Try to pass rowToDelete = 0 and then check – Keshu R. Dec 29 '19 at 06:20
  • in the logs it just shows "index not present" but on the bright side it doesn't crag the simulator anymore, but still fails too delete the cell in the section – Evelyn Dec 29 '19 at 06:48
  • 1
    You have multiple sections in your TableView, you need to get the section too. `[IndexPath(row: rowToDelete, section: 0)]` here we also need to pass section – Keshu R. Dec 29 '19 at 06:50
  • I just posted an image to show you what exactly im trying to do, I was thinking it might be because of how I have my cellForRowAt set up and how it breaks my food items into their sections – Evelyn Dec 29 '19 at 06:59
  • the deletebtn in the calorieCell is performing the segue through the storyboard and the code is all there for the cellForRowAt already – Evelyn Dec 29 '19 at 07:15