1

I would like to have synchronized http request results with my Core Data database. For example very basic class:

class Category: NSManagedObject {

    @NSManaged var id: NSNumber
    @NSManaged var name: String
    @NSManaged var imageUrl: String
}

And I have this method for getting results from request:

    apiManager.getRequestJsonParse(Constants.Server.BackendUrl + "categories?lang=cs", completion: { (result, error) -> Void in

        completion(categories: [], error: error)
    })

Result is dictionary parsed from json. It's okay but now I want to parse dictionary to my class, check if exists in database, if it exists update properties and if not than add new category to database.

My approach that I was using in apps before was that I have two classes: Category and CategoryCD (CD like Core Data) and first I parse json to Category class than for all categories I check if any CategoryCD (saved in CD) has same Id and then update, or add or other things.

Now I am thinking if there is better way how can I do it. I could each time when I download new results delete my database for this class and then add all results. The problem with this way is that what if I have something for some classes that I want keep. Like if I download and save images then I would rather still have connection between class and saved image.

I was thinking about my old approach but reduce 2 almost same classes (1 for Core Data and 1 same but for parsing) to 1 Core Data class. But then there is a problem when I init this class I must always create in database right? So It could be complicated.

What are you using for this? I think it's very common problem. You have list of items and I would like to have them available offline (with all data I downloaded before) but than when I connect to internet I would like to update with new results (not download all from server, just responses which I requested).

2 Answers 2

1

It is a very common problem and it has been solved hundreds of ways. BTW, This is not "synchronizing" it is "caching" for offline use.

Do not create two objects as that is redundant. Create just the Core Data objects as part of the parse.

A standard JSON parse would look like this:

  1. Convert to Objects using NSJSONSerializer.
  2. Fetch all unique IDs from the JSON objects using KVO
  3. Fetch all existing objects from Core Data based on uniqueIDs
  4. Insert all objects that do not currently exist

If you are going to update objects then #4 would do both.

Search on Stackoverflow and you will find plenty of examples of how to do this.

Sign up to request clarification or add additional context in comments.

Comments

1

I do something similar in one of my apps. Here is some generic code to fetch an item and update it. If it doesn't exist, it creates it.

func insertOrUpdateManagedObject(id: Int16, name: String) -> YourManagedObject? {
  var managedObject: YourManagedObject?
  if let context = self.managedObjectContext {
    if let fetchResult = fetchManagedObjectWithId(id) {
      managedObject = fetchResult
      managedObject?.name = name
    }
    else {
      managedPhrase =   NSEntityDescription.insertNewObjectForEntityForName("YourManagedObject", inManagedObjectContext: context) as? YourManagedObject
      managedObject?.id = id
      managedObject?.name = name
    }
  }

  println("Created a managed object \(managedObject)")
  return managedObject
}

6 Comments

The performance on that code would be terrible. You are doing a fetch for each individual object to determine if it exists or not. That is N hits to the disk. Instead you should use KVO to get all the uniqueIDs from the incoming JSON and do ONE call to the disk for existing objects. Then you can iterate.
@MarcusS.Zarra oh I'm aware of that. This however is for a single entry. I'm sure the op can adapt the code to suit his needs
When you write examples like this you end up seeing code that just iterates over this method. Better to be clear from the beginning about the danger of this lest the OP complain that CD is slow... ;-)
@MarcusS.Zarra will in future. Thank you :)
@Lytic, my error. I meant KVC. You would use valueForKeyPath: to aggregate the UniqueIDs.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.