1

I am trying to implement CoreData in my app with SwiftUI.

I have create the entity Aeroporti with 2 attributes icaoAPT and iataAPT

My app downloads some data from a Firebase database and save the data locally for offline usage.

I managed to saved all data in the entity Aeroporti but now I want to create a function to delete all data stored, before the user is going to download the updated data again.

I manage to delete the data at single index directly in the contentView with the func cancella().

But now I am facing a problem with the func delate all in the DataManager.


import SwiftUI
import CoreData

struct ContentView: View {
    @ObservedObject var dm : DataManager
    @Environment(\.managedObjectContext) var managedObjectContext
    
    @FetchRequest(entity: Aeroporti.entity(),
                  sortDescriptors: [NSSortDescriptor(keyPath: \Aeroporti.iataAPT, ascending: true)]) var aeroport : FetchedResults<Aeroporti> // crea la variabile che contiene le ricette
   
    var body: some View {
        VStack{
              HStack{
                
                Button(action: {
                    DataManager.shared.downloadData(dbCore: self.managedObjectContext)
                }) {
                    Text("save from manager")
                }
                
                Spacer()
                
                Button(action: {
                    DataManager.shared.delateALL(dbCore: self.managedObjectContext)
                }) {
                    Text("del all")
                }
                
                
            }
        List{
          
            ForEach(aeroport, id: \.self) { apt in
                VStack{
                Text(apt.iataAPT ?? "sconosciuto")
                Text(apt.icaoAPT ?? "sconosciuto")
                }
            }
            .onDelete(perform: cancella)
        }
        
    }
    
    }
    // this delate at single index
    func cancella(at offset : IndexSet) { //1 ricevo indice ricetta , indexset è un array di indici
           
           for index in offset { // 2 ciclo dentro l'array offset con dentro gli indici
              let apt = aeroport[index] // 3 tiro furoi la ricetta a quel indice
               
               managedObjectContext.delete(apt) // 7 cancella alla fine la ricetta
           }
           do { // 8 salvo
               try self.managedObjectContext.save()
              
              
           } catch {
               debugPrint(error.localizedDescription)
           }
       }
}

I want to delate all record in the entity Aeroporti, I have try to write this, but of course I'm stuck:

class DataManager:  ObservableObject {
    
    let objectWillChange = PassthroughSubject<Void, Never>()
    let db = Firestore.firestore()
    static let shared = DataManager()
    

    
    // get data from Firestore and Save locally
    func downloadData(dbCore: NSManagedObjectContext ) {
    
            db.collection("VHHH").document("VHHHid").getDocument { (document, error) in
                if error == nil {
                    if document != nil && document!.exists  {
    
                        let data = document!.data()

    
                        let icaoAPT = data?["icaoAPT"] ?? "empty"
                        let iataAPT = data?["iataAPT"] ?? "empty"
    
                        let aeroporto = Aeroporti(context: dbCore)
                        aeroporto.icaoAPT = icaoAPT as? String
                        aeroporto.iataAPT = iataAPT as? String
    
                        debugPrint(aeroporto.iataAPT!)
                        
                        do {
                            try dbCore.save()
                            print("Saved Data")
                        } catch {
                            
                            let nserror = error as NSError
                            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
                        }
                    }
                }
            }
        }
    

    // test delate all...NOT WORKING
    func delateALL(dbCore: NSManagedObjectContext, vett: FetchedResults<NSFetchRequestResult>){
 
//        let req = NSFetchRequest<NSFetchRequestResult>(entityName: "Aeroporti")
        
         // 3 tiro furoi la ricetta a quel indice
        for data in vett {
          let data1 = vett[0]
//            dbCore.delete(data1)
        }
    }

    // delate all but not update
//    func delateALL2(dbCore: NSManagedObjectContext){
//        let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Aeroporti")
//        let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
//
//
//        do {
//            try dbCore.execute(deleteRequest)
//            debugPrint("canx all")
//
//            do {
//                try dbCore.save()
//                print("Saved Data")
//            } catch {
//
//                let nserror = error as NSError
//                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
//            }
//
//        } catch let error as NSError {
//            debugPrint(error)
//        }
//
//    }

}

thanks for the helping me

1 Answer 1

2
func deleteRecords() {
        // References to context
        let context = App.persistency.container.viewContext

        let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Aeroporti")
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)

        do {
            try context.persistentStoreCoordinator?.execute(deleteRequest, with: context)
        } catch let error as NSError {
            print("Fetch failed. \(error.localizedDescription)")
        }
    }

In order to update your UI, you could make something like:

  1. Create an @State private var airportCount: Int?
  2. In your body content, add an onAppear(_:) modifier, and add to airportCount the correct airport total count you have in your DB once the view is loaded.
  3. When you invoke the method deleteRecords(), be sure to update your airportCount variable with the new number (0), and your view will be updated.

And that's it. The view should reload.

2
  • it works, but the contentView not updated immediately.. it empty only after restart the app Commented Jun 29, 2020 at 15:42
  • Ohh, okay, I edit my answer in order to update also the UI. There are a lot of ways to achieve the view update, but this is the simpler.
    – AlbertUI
    Commented Jun 29, 2020 at 17:23

Not the answer you're looking for? Browse other questions tagged or ask your own question.