Reputation: 417
I'm trying to save a bunch of data into core data. I could manage to save all the data into core data but it make no sense to have duplicate data inside core data because the function will be execute once on every build of the project. The approach that I am thinking now is empty the entity's record before I am adding new record to it. Just want to know is that got another way around to make sure that the data only persist once?
func persistCurrencyData() {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let currencyEntity = NSEntityDescription.entityForName("Currency", inManagedObjectContext: managedContext)
let countryEntity = NSEntityDescription.entityForName("Country", inManagedObjectContext: managedContext)
for currency in currencies {
let currencyObject = CurrencyCore(entity: currencyEntity!, insertIntoManagedObjectContext: managedContext)
currencyObject.setValue(currency.code, forKeyPath: "code")
currencyObject.setValue(currency.name, forKeyPath: "name")
for country in currency.country! {
let countryObject = CountryCore(entity: countryEntity!, insertIntoManagedObjectContext: managedContext)
countryObject.setValue(country.name, forKeyPath: "name")
countryObject.setValue(country.code, forKeyPath: "code")
countryObject.setValue(country.continent, forKeyPath: "continent")
countryObject.setValue(country.continentCode, forKeyPath: "continentCode")
countryObject.currency = currencyObject
}
}
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
Update:
Thanks to @Wain for giving me the idea. Basically what I done to solve the saving of duplicate data in core data is I included an GUID in my JSON file. Every time the code read the JSON file, it will save GUID into NSUserDefault
and save data into core data. When it wants to read JSON file again in the next build, it will check whether the GUID is same as previous saved GUID. If it is different, the code will read the JSON file and repeat the process above. If not, it will proceed and ignore it.
func requestCurrenciesData() {
getCurrenciesDataFromFileWithSuccess { (data) -> Void in
var json: [String: AnyObject]
do {
json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as! [String: AnyObject]
guard let currencyData = CurrencyData(json: json) else {
print("Error initializing object")
return
}
self.currencies = currencyData.currency!
// Checking the JSON's id is same as previous read
let defaults = NSUserDefaults.standardUserDefaults()
if let id = defaults.stringForKey("id")
{
if id == currencyData.id {
let notification = NSNotification(name: "CurrenciesDataUpdate", object: nil)
NSNotificationCenter.defaultCenter().postNotification(notification)
return
}
}
self.persistCurrencyDataForId(currencyData.id)
let notification = NSNotification(name: "CurrenciesDataUpdate", object: nil)
NSNotificationCenter.defaultCenter().postNotification(notification)
} catch {
print(error)
return
}
}
}
func persistCurrencyDataForId(id: String) {
// Save the new JSON's id into NSUserDefaults
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(id, forKey: "id")
// Delete all the records in existing table
deleteRecordsFromEntity("Country")
deleteRecordsFromEntity("Currency")
// Insert the new records
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let currencyEntity = NSEntityDescription.entityForName("Currency", inManagedObjectContext: managedContext)
let countryEntity = NSEntityDescription.entityForName("Country", inManagedObjectContext: managedContext)
for currency in currencies {
let currencyObject = CurrencyCore(entity: currencyEntity!, insertIntoManagedObjectContext: managedContext)
currencyObject.setValue(currency.code, forKeyPath: "code")
currencyObject.setValue(currency.name, forKeyPath: "name")
for country in currency.country! {
let countryObject = CountryCore(entity: countryEntity!, insertIntoManagedObjectContext: managedContext)
countryObject.setValue(country.name, forKeyPath: "name")
countryObject.setValue(country.code, forKeyPath: "code")
countryObject.setValue(country.continent, forKeyPath: "continent")
countryObject.setValue(country.continentCode, forKeyPath: "continentCode")
countryObject.currency = currencyObject
}
}
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
func deleteRecordsFromEntity(entityName: String) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let coordinator = appDelegate.persistentStoreCoordinator
let fetchRequest = NSFetchRequest(entityName: entityName)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try coordinator.executeRequest(deleteRequest, withContext: managedContext)
} catch let error as NSError {
print(error)
}
}
Upvotes: 4
Views: 97
Reputation: 119021
In general you can say 'if i have any currency entries in the data store, don't add more'. That could be done by adding a flag to use defaults or something like that when you do the first import, but a better option is to check the data store to see if it has any currency entries. To do this create a fetch request for currencyEntity
and use countForFetchRequest:error:
before you carry on with for currency in currencies {
. If the count is greater than zero then you should return instead of processing the loop.
To be more efficient this check should actually be before you download and process the JSON...
Upvotes: 1