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)
}
}
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...
Related
How can i restrict duplicate entry in core data
//MARK:- save in core data
let appDel1:AppDelegate = UIApplication.shared.delegate as! AppDelegate
let context:NSManagedObjectContext = appDel1.persistentContainer.viewContext
let userObj:NSManagedObject = NSEntityDescription.insertNewObject(forEntityName: "RPAData", into: context)
userObj.setValue(rpaType, forKey: "rpatype")
userObj.setValue(rpaReg, forKey: "rparegistration")
userObj.setValue(identificationNumber, forKey: "identificationnumber")
userObj.setValue(rpaTypeId, forKey: "rpatypeid")
do{
try context.save()
print("rpaReg , identificationNumber , rpaTypeId and rpaType Saved in core Data...")
} catch {
print("Error in save - ", error)
}
If the combination of all the 4 entries(rpaReg , identificationNumber , rpaTypeId and rpaType) are same than these data will not save in core data and an alert will be shown.
this is how i fetch data from core data
var dataArray:[NSManagedObject] = []
let appDel1:AppDelegate = UIApplication.shared.delegate as! AppDelegate
let context:NSManagedObjectContext = appDel1.persistentContainer.viewContext
let fetchRequest:NSFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "RPAData")
do
{
dataArray = try context.fetch(fetchRequest) as! [NSManagedObject]
} catch {
print("error =>",error)
}
Add some constraints in your entity
Then use this to show error when saving failure (default value)
context.mergePolicy = NSErrorMergePolicy
How to save data in offline using coredata, and if network comes(online) send the saved data to the API?
This is the code to save data:
func savePSaveInfo(cId: String, pId:String, createdBy:String, agep:String, languageId:String, emailId:String, mobileNumber:String,backendUpdate: Bool)
{
let nameObj = NSEntityDescription.insertNewObject(forEntityName: "SaveInfo", into: context!) as! SaveInfo
nameObj.cId = cId
nameObj.pId = pId
nameObj.createdBy = createdBy
nameObj.agep = agep
nameObj.languageId = languageId
nameObj.emailId = emailId
nameObj.mobileNumber = mobileNumber
nameObj.backendUpdate = backendUpdate
do{
try context!.save()
}catch{
print("not saved")
}
}
For inserting value in core data, I am sharing a example , you can set according to you data.
Step 1 :- Set the entity like this
Step 2:-
//MARK:- FOR CREATING NEW DATA
func createData(){
//As we know that container is set up in the AppDelegates so we need to refer that container.
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
//We need to create a context from this container
let managedContext = appDelegate.persistentContainer.viewContext
//Now let’s create an entity and new user records.
let userEntity = NSEntityDescription.entity(forEntityName: "User", in: managedContext)!
//final, we need to add some data to our newly created record for each keys using
let user = NSManagedObject(entity: userEntity, insertInto: managedContext)
user.setValue(txtFldUsername.text!, forKeyPath: "username")
user.setValue(txtFldEmail.text!, forKey: "email")
user.setValue(txtFldPassword.text!, forKey: "password")
retrieveData()
//Now we have set all the values. The next step is to save them inside the Core Data
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
Stop 3:- For fetching data
//MARK:- FOR RETRIEVING OR FETCHING THE DATA
func retrieveData() {
//As we know that container is set up in the AppDelegates so we need to refer that container.
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
//We need to create a context from this container
let managedContext = appDelegate.persistentContainer.viewContext
//Prepare the request of type NSFetchRequest for the entity
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "User")
do {
let result = try managedContext.fetch(fetchRequest)
arrUserDetails.removeAll()
for data in result as! [NSManagedObject] {
print(data.value(forKey: "username") as! String)
arrUserDetails.append(userData(username: (data.value(forKey: "username") as! String), email: (data.value(forKey: "email") as! String), password: (data.value(forKey: "password") as! String)))
}
tblView.reloadData()
} catch {
print("Failed")
}
}
Still there is any issue , let me know about the query
I have two entities on core-data one is user list and another one is data list. under every user in the user list, their own data list should be saved. How can i achieve this? I tried some code, but nothing helps me.
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
let entity =
NSEntityDescription.entity(forEntityName: "DataList",
in: managedContext)!
let data = NSManagedObject(entity: entity,
insertInto: managedContext)
// setting fields
data.setValue(self.txtTitle.text!, forKeyPath: "title")
data.setValue(self.txtShortNote.text!, forKeyPath: "short_note")
data.setValue(self.txtDescription.text!, forKeyPath: "data_description")
// setting image
let imageData = self.imgDocument.image!.jpegData(compressionQuality: 0.01)
let base64Str = imageData?.base64EncodedString(options: .lineLength64Characters)
data.setValue(base64Str, forKeyPath: "image")
// setting date
let currentDate = Date()
let dateFormatter = DateFormatter()
let dateString = dateFormatter.string(from: currentDate)
data.setValue(dateString, forKeyPath: "date")
// save
do {
try managedContext.save()
arrDataList.append(data)
SharedManager.showToast(message: "Data Added Successfully", viewController: self)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
This is how im saving Data into Data list.
As Im new to core-data please help me to solve this. Any sample codes would be more appreciated.
Thanks in advance..!
I am building an app, in which I want to populate UITableViewCell from CoreData. In CoreData I am able to save data from server and also able to fetch data. But when my internet is offline I am unable to retrive data from CoreData or there is no data in CoreData. How can I fetch last saved data from CoreData when my internet is offline?
I am saving data using following function:
func SetPremiumValues(Array : NSArray){
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("PremiumJob", inManagedObjectContext:managedContext)
for i in Array{
let PremiumJob = NSManagedObject(entity: entity!,insertIntoManagedObjectContext: managedContext)
if let rowData :NSDictionary = i as? NSDictionary{
PremiumJob.setValue(rowData["company"], forKey: "company")
PremiumJob.setValue(rowData["city"], forKey: "city")
PremiumJob.setValue(rowData["id"], forKey: "id")
let ImageName = rowData["user_logo"] as? String
let image = "http://dev.jobsmarket.pk/uploads/user-logo/"+ImageName!
let url = NSURL(string: image)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
if let data = NSData(contentsOfURL: url!) {
PremiumJob.setValue(data, forKey: "user_logo")
}
}
PremiumJob.setValue(rowData["title"], forKey: "title")
PremiumJob.setValue(rowData["fe_short_description"], forKey: "fe_short_description")
}
do {
try managedContext.save()
print("saving premium job is this \(PremiumJob)")
self.Premium.append(PremiumJob)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
}
// fetching data using fetch request
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "PremiumJob")
do{
let results = try managedContext.executeFetchRequest(fetchRequest)
for ManagedObject in results {
let managedObjectData : NSManagedObject = ManagedObject as! NSManagedObject
print("premium data from fetch request \(managedObjectData)")
}
}
catch{
}
}
I want to save my data to core data when a button is clicked here is my action button code now let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let entity = NSEntityDescription.entityForName("Cart", inManagedObjectContext: context)
let cart = Cart(entity: entity!, insertIntoManagedObjectContext: context) but the only problem now is that i dont how to save here is my code to parse json
Alamofire.request(.GET, url!, headers: headers).responseJSON { (response) in
let result = response.result
if response.result.isSuccess{
let jsonObj = JSON(result.value!)
if let x = jsonObj["Items"].array {
x.forEach
{
if let uw = ($0["name"]).string{
print(uw)
let qw = ($0["image"]).string
if let rw = ($0["price"]).int{
if let hu = ($0["id"]).int{
print(hu)
let foo = Rest(name: uw, imageUrl: qw!, price: "₦\(rw)")
self.rest.append(foo)
}
}
}
}
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
actInd.stopAnimating()
}
}
}
So i have an array called rest which is where i want get data for the tableview. I want to save information of each cell tapped into coredata here is a screenshot of the app
So when the sure button is tapped it saves the item to coredata
here is my code incase you neecode
Try this, adapted to your code.
In the portion that you have (...let app=...) replace it by this:
let app2 = UIApplication.sharedApplication().delegate as! UIApplicationDelegate
if let context2 = app2.managedObjectContext {
let cart2 = NSEntityDescription.insertNewObjectForEntityForName("Cart", inManagedObjectContext: context2) as! Cart
cart2.name = self.res.name
cart2.price = self.res.price
cart2.url = self.res.imageUrl
cart2.id = ""
// Perform a save operation
do {
try context2?.save()
} catch {
let saveError = error as NSError
print(saveError)
}
}
Let me know if this works.
Cheers
Just an example here when you want to save your data in coredata. You have to create entity/model and all the setup for core data elements. For details please study https://www.raywenderlich.com/115695/getting-started-with-core-data-tutorial
func saveName(name: String) {
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
//2
let entity = NSEntityDescription.entityForName("Person",
inManagedObjectContext:managedContext)
let person = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
//3
person.setValue(name, forKey: "name")
//4
do {
try managedContext.save()
//5
people.append(person)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}