Save When Program Exits

I'm trying to use CoreData to save my favourites so that they will be accessed when the program terminates but I am not sure how to make my object persistent to do that.

Code Block
   @IBAction func addToFav(_ sender: Any) {
        let alert = UIAlertController(title: "Favourite Added 💙", message: "\(name.text ?? "") is added to favourites", preferredStyle: .alert)
        alert.addAction(UIAlertAction(
          title: "OK",
          style: UIAlertAction.Style.default)
          { _ in
        if let favPlayer = self.item /*this needs to be persistent*/ {
            FavouriteManager.shared.add(favPlayer)
            PersistenceService.saveContext()
             }
          })
        self.present(alert, animated: true, completion: nil)
        print("Favourite button Pressed")
      }


I have a PersistenceService class I can more easily access my CoreData values.

Code Block
class PersistenceService {
   
  private init() {}
     
    static var context: NSManagedObjectContext {
      return persistentContainer.viewContext
    }
// MARK: CoreData
static var persistentContainer: NSPersistentContainer = {
  let container = NSPersistentContainer(name: "playerModel")
  container.loadPersistentStores(completionHandler: { (storeDescription, error) in
    if let error = error as NSError? {
      // Replace this implementation with code to handle the error appropriately.
      // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
       
      fatalError("Unresolved error \(error), \(error.userInfo)")
    }
  })
  return container
}()
static func saveContext () {
  let context = persistentContainer.viewContext
  if context.hasChanges {
    do {
      try context.save()
    } catch {
      // Replace this implementation with code to handle the error appropriately.
      // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
      let nserror = error as NSError
      fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
    }
  }
}
}

Answered by ZoneX in 671586022
I will close the thread because we got nowhere.
To save when the app exits, go to the AppDelegate.swift file. For an iOS app there will be a function called applicationWillResignActive. In a Mac app, the function will be called applicationWillTerminate. These functions are called when quitting the app.

Call the saveContext function in either applicationWillResignActive or applicationWillTerminate.
Okay I have the function you are talking about in AppDelegate but it does not save my data when I terminate the app. Are you sure I don't have to make the object persistent?

Code Block
   func applicationWillTerminate(_ application: UIApplication) {
      /* Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground*/
      PersistenceService.saveContext()
    }



Make sure the saveContext function is called by setting a breakpoint on that line of code. Does it get called in applicationWillTerminate?

I made a mistake in my first reply. For an iOS app the function where you should save the context is applicationDidEnterBackground. That's the function that will be called when someone quits the app. The applicationWillTerminate function does not get called until the app is purged from memory completely, which requires the user to launch several apps after quitting your app.

Can you explain what you mean by "make the object persistent"? Saving the context is how you save data in Core Data.
szymczyk says

Make sure the saveContext function is called by setting a breakpoint on that line of code. Does it get called in applicationWillTerminate?


I made a mistake in my first reply. For an iOS app the function where you should save the context is applicationDidEnterBackground. That's the function that will be called when someone quits the app. The applicationWillTerminate function does not get called until the app is purged from memory completely, which requires the user to launch several apps after quitting your app.



I tried your solution but it still does not save the favourites when it terminates and the function does not get called at all.

Code Block
 func applicationDidEnterBackground(_ application: UIApplication) {
      PersistenceService.saveContext()
  }


szymczyk says

Can you explain what you mean by "make the object persistent"? Saving the context is how you save data in Core Data.

I'm thinking that I have to initialize my item object with NSManagedContext so that it can be saved locally to the device.


Do it here (and test with the print):

Code Block
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
print("End")
// Save here
}


Claude31 says

Do it here (and test with the print):

The function is still not being called.
If this is really when you want to save(), I suggest reading up on the lifecycle of an app and using appropriate scene delegate methods if that’s the flow your app used.

Of course, iOS doesn’t ever really tell you if your app has been force-terminated by the user.
awal says

If this is really when you want to save(), I suggest reading up on the lifecycle of an app and using appropriate scene delegate methods if that’s the flow your app used. 


Of course, iOS doesn’t ever really tell you if your app has been force-terminated by the user.



applicationWillTerminate seems like the appropriate method because it's called when the user terminates the app without switching it to the background.
Accepted Answer
I will close the thread because we got nowhere.
Save When Program Exits
 
 
Q