Problem with Core Data and fetch requests

Hi guys basically i have one one view that contains a UITableView, the table can add and delete entrys and saves its state in core datat stack. the view is a food diary and I have set up the view to keep all objects inserted and deleated persistent when the user add and removes a food entry. While this works for a single app session the table will not allow me to delete an entry when the i restart the app, but the last entered food is still displayed on screen.


If i try to delete the entry the application begins to crash. The core data entities are as follows Calories, Food and Exercise. I am gussing the fetch request located at the below of this code returns an array with zero objects and that why it will not me delete somthing that does not exists. I have posted the code below for somone to guide or help me out.


Thanks


import UIKit
import SwifterSwift
import CoreData
class DiaryView: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate, UITextFieldDelegate {
  
    var userFoods:[String] = []
    var userCalories:[String] = []
    var userServings:[String] = []
    var counter: Double = 0
  
    var food = [Food]()
    var calorie = [Calorie]()
  
    @IBOutlet weak var userFoodTextField: UITextField!
    @IBOutlet weak var userCaloriesTextField: UITextField!
    @IBOutlet weak var userServingTextField: UITextField!
    @IBOutlet weak var foodTable: UITableView!
  
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        fetchUsersFood()
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        foodTable.delegate = self
        foodTable.dataSource = self
    }
    @IBAction func insertFoodAction(_ sender: Any) {
        insertFoodAction()
    }
}
extension DiaryView{
  
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.food.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      
        let  cell = tableView.dequeueReusableCell(withIdentifier: "foodCell") as! DiaryViewCustomCell
        let foods = food[indexPath.row]
        cell.foodnameLabel.text = foods.foodName
        cell.calorieamountLabel.text = foods.calorieAmount + " " + "kcal"
        cell.servingLabel.text = foods.servingAmount + " " + "servings"
        return cell
    }
  
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
          
            let lastCalorieAmount = calorie[indexPath.row]
            let lastServingAmount = food[indexPath.row]
          
            counter = lastCalorieAmount.totalCalorie.double()! - (lastServingAmount.servingAmount.double()! * lastServingAmount.calorieAmount.double()!)
          
            deleteUserFood(at: indexPath)
            saveLastestCalories(updatedValue: counter)
          
            userFoods.remove(at: indexPath.row)
            userCalories.remove(at: indexPath.row)
            userServings.remove(at: indexPath.row)
            foodTable.beginUpdates()
            foodTable.deleteRows(at: [indexPath], with: .automatic)
            foodTable.endUpdates()
            view.endEditing(true)
        }
    }
  
    func insertFoodAction()  {
        if userFoodTextField.text == "" || userCaloriesTextField.text  == "" || userServingTextField.text == "" {
            userFoodTextField.shake()
            userCaloriesTextField.shake()
            userServingTextField.shake()
        }
        else {
          
            let indexPathFood = IndexPath(row: userFoods.count - 1, section: 0)
            let indexPathCalories = IndexPath(row: userCalories.count - 1, section: 0)
            let indexPathServing = IndexPath(row: userServings.count - 1, section: 0)
          
            counter = counter + (userCaloriesTextField.text?.withoutSpacesAndNewLines.double())! * (userServingTextField.text?.withoutSpacesAndNewLines.double())!
            saveUserFood()
            saveLastestCalories(updatedValue: counter)
          
          
            userFoods.append((userFoodTextField.text?.trimmed)!)
            userCalories.append((userCaloriesTextField.text?.trimmed)!)
            userServings.append((userServingTextField.text?.trimmed)!)
          
            foodTable.beginUpdates()
            foodTable.insertRows(at: [indexPathFood, indexPathCalories, indexPathServing], with: .automatic)
            foodTable.endUpdates()
          
            userFoodTextField.text = ""
            userCaloriesTextField.text = ""
            userServingTextField.text = ""
            view.endEditing(true)
        }
    }
  
    func saveUserFood()  {
        guard let applicationDelegate = UIApplication.shared.delegate as? AppDelegate else{return}
        let managedContext =  applicationDelegate.persistentContainer.viewContext
        let entity = NSEntityDescription.entity(forEntityName: "Food", in: managedContext)!
        let foods = Food(entity: entity, insertInto: managedContext)
        foods.foodName = (userFoodTextField.text?.trimmed)!
        foods.calorieAmount = (userCaloriesTextField.text?.trimmed)!
        foods.servingAmount = (userServingTextField.text?.trimmed)!
        foods.userFoodDate = Date()
      
        do{
            try managedContext.save()
            food.append(foods)
        } catch let error as NSError{
            print("Could not save user food. \(error.userInfo)")
        }
    }
  
    func deleteUserFood(at indexPath: IndexPath)  {
        guard let applicationDelegate = UIApplication.shared.delegate as? AppDelegate else{return}
        let context = applicationDelegate.persistentContainer.viewContext
        context.delete(food[indexPath.row] as NSManagedObject)
        food.remove(at: indexPath.row)
        do{
            try context.save()
        } catch let error as NSError{
            print("Could not save user food. \(error.userInfo)")
        }
    }
  
    func saveLastestCalories(updatedValue:Double)  {
        guard let applicationDelegate = UIApplication.shared.delegate as? AppDelegate else{return}
        let managedContext =  applicationDelegate.persistentContainer.viewContext
        let entity = NSEntityDescription.entity(forEntityName: "Calorie", in: managedContext)!
        let calories = Calorie(entity: entity, insertInto: managedContext)
        calories.totalCalorie = updatedValue.int.string
        calories.date = Date()
        do{
            try managedContext.save()
            calorie.append(calories)
            print(calories.totalCalorie)
        } catch let error as NSError{
            print("Could not save user food. \(error.userInfo)")
        }
    }
  
    func fetchUsersFood() {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        }
        let managedObjectContext = appDelegate.persistentContainer.viewContext
        let fecthRequest = NSFetchRequest<NSManagedObject>(entityName: "Food")
        fecthRequest.sortDescriptors = [NSSortDescriptor(key: "userFoodDate", ascending: false)]
      
        do {
            food = try managedObjectContext.fetch(fecthRequest) as! [Food]
            print(food)
        } catch let error as NSError {
            print("Could not fetch data. \(error), \(error.userInfo)")
        }
    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 70.0
    }
    func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        return true
    }
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
    override var preferredStatusBarStyle: UIStatusBarStyle{
        return .lightContent
    }
}

Replies

Can you please provide the line of exception? Is it 155 ?