Search code examples
core-dataswiftui

Update CoreData when fetch again from online Json


I am fetching data from Json and save all at once in CoreData. I introduced a new entity "isFavorite" to mark core data posts as favorites. The problem is that after i fetch again from server the isFavorite data is resseting to the default false.

I save the data like this:

import SwiftUI
import CoreData

class JSONViewModel: ObservableObject {

    @Published var listings: [ListingModel] = []
    // saving Json to Core Data...
    
    func saveData(contex: NSManagedObjectContext) {
        
        listings.forEach { (data) in
            
            let entity = Listing(context: contex)
            
            entity.id = Int64(data.id)
            entity.title = data.title
            entity.name = data.name
            entity.latitude = Double(truncating: NSNumber(value: data.latitude))
            entity.longitude = Double(truncating: NSNumber(value: data.longitude))
            entity.isFavorite = false // everytime i fetch again all the post get default value as isFavorite = false, 

witch is overighting tha acual post's witch have already isFavorite = true

        }

        do{
           // saving all pending data at once
           try contex.save()

            print("success")
        }
        catch{
            print(error.localizedDescription)
        }
       
    }
    
    
    func fetchData(context: NSManagedObjectContext){
        
        let url = "https://... on line json"
        
        var request = URLRequest(url: URL(string: url)!)
        request.addValue("swiftui2.0", forHTTPHeaderField: "field")
        
        let session = URLSession(configuration: .default)
        
        session.dataTask(with: request) { (data, res, _) in
            
            guard let jsonData = data else{return}
            
            // check for errors
            
            let response = res as! HTTPURLResponse
            // checking by status code
            
            if response.statusCode == 404 {
                print("error Api Errror")
            }
            
            // fetching JSON Data ..
            do {
                let listings = try JSONDecoder().decode([ListingModel].self, from: jsonData)
                
                DispatchQueue.main.async {
                  
                    self.listings = listings
                    self.saveData(contex: context)
                }
            }
            catch {
                print(error.localizedDescription)
            }
        }
        
        .resume()
    }
}

How can i check if data exist and only change what is new?

i have also set Constraints by "id". and updated the PersistentContainer like this::

 let container: NSPersistentContainer
   
    init(inMemory: Bool = false) {
        
        container = NSPersistentContainer(name: "WebyCoreData")
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")       }
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        
    }

Any help is deeply appreciated!

Have tried also:

if entity.isFavorite == true {
                entity.isFavorite = true}
            else {
                entity.isFavorite = false}

Solution

  • In your saveData function, try something like this:

     let listingFetch: NSFetchRequest<Listing> = Listing.fetchRequest()
      listingFetch.predicate = NSPredicate(format: "id == %@", Int64(data.id))
    
        do {
         let results:[Listing] = try contex.fetch(listingFetch)
            if results.count == 0 {
    
               let entity = Listing(context: contex)
               entity.id = Int64(data.id)
               entity.title = data.title
               entity.name = data.name
               entity.latitude = Double(truncating: NSNumber(value: data.latitude))
               entity.longitude = Double(truncating: NSNumber(value: data.longitude))
               entity.isFavorite = false
    
                try? contex.save()
               print ("Inserted Listing")
            }
            else
            {
               let entity = results[0]
               entity.title = data.title
               entity.name = data.name
               entity.latitude = Double(truncating: NSNumber(value: data.latitude))
               entity.longitude = Double(truncating: NSNumber(value: data.longitude))
               entity.isFavorite = true
    
                try? contex.save()
                print ("Updated Listing")
            }
        } catch let error as NSError {
            print("error inserting / updating Listing \(error), \(error.userInfo)")
        }
    

    Update with Marius's full list of properties. Also modified typo

        func saveData(contex: NSManagedObjectContext) {
            
           
            listings.forEach() { (data) in
                
            let listingFetch: NSFetchRequest<Listing> = Listing.fetchRequest()
              listingFetch.predicate = NSPredicate(format: "id = %@", data.id)
            
           
                do {
                 let results:[Listing] = try contex.fetch(listingFetch)
                    if results.count == 0 {
    
                       let entity = Listing(context: contex)
                        entity.id = Int64(data.id)
                        entity.title = data.title
                        entity.name = data.name
                        entity.category = data.category
                        entity.image = data.image
                        entity.publishdate = data.publishdate
                        entity.tagline = data.tagline
                        entity.content = data.content
                        entity.coverimage = data.coverimage
                        entity.galleryunu = data.galleryunu
                        entity.gallerydoi = data.gallerydoi
                        entity.gallerytrei = data.gallerytrei
                        entity.saleprice = Int64(truncating: NSNumber(value: data.saleprice))
                        entity.rentprice = Int64(truncating: NSNumber(value: data.rentprice))
                        entity.phone = data.phone
                        entity.email = data.email
                        entity.area = Int64(truncating: NSNumber(value: data.area))
                        entity.rooms = Int64(truncating: NSNumber(value: data.rooms))
                        entity.beds = Int64(truncating: NSNumber(value: data.beds))
                        entity.bathrooms = Int64(truncating: NSNumber(value: data.bathrooms))
                        entity.expires = data.expires
                        entity.adresa = data.adresa
                        entity.listingtype = data.listingtype
                        entity.latitude = Double(truncating: NSNumber(value: data.latitude))
                        entity.longitude = Double(truncating: NSNumber(value: data.longitude))
                       entity.isFavorite = false
    
                        try? contex.save()
                       print ("Inserted Listing")
                    }
                    else
                    {
                       let entity = results[0]
                        entity.id = Int64(data.id)
                        entity.title = data.title
                        entity.name = data.name
                        entity.category = data.category
                        entity.image = data.image
                        entity.publishdate = data.publishdate
                        entity.tagline = data.tagline
                        entity.content = data.content
                        entity.coverimage = data.coverimage
                        entity.galleryunu = data.galleryunu
                        entity.gallerydoi = data.gallerydoi
                        entity.gallerytrei = data.gallerytrei
                        entity.saleprice = Int64(truncating: NSNumber(value: data.saleprice))
                        entity.rentprice = Int64(truncating: NSNumber(value: data.rentprice))
                        entity.phone = data.phone
                        entity.email = data.email
                        entity.area = Int64(truncating: NSNumber(value: data.area))
                        entity.rooms = Int64(truncating: NSNumber(value: data.rooms))
                        entity.beds = Int64(truncating: NSNumber(value: data.beds))
                        entity.bathrooms = Int64(truncating: NSNumber(value: data.bathrooms))
                        entity.expires = data.expires
                        entity.adresa = data.adresa
                        entity.listingtype = data.listingtype
                        entity.latitude = Double(truncating: NSNumber(value: data.latitude))
                        entity.longitude = Double(truncating: NSNumber(value: data.longitude))
                       entity.isFavorite = true
    
                        try? contex.save()
                        print ("Updated Listing")
                    }
                } catch let error as NSError {
                    print("error inserting / updating Listing \(error), \(error.userInfo)")
                }
            }
        }