Saving multiple objects for an attribute in CoreData - swift

CoreData Structure:
Entity: ZooAnimals, Attributes: animal (String type) and count (Integer 16 type)
I want to save in some animal names and the quantity (count) of each animal. I can do this by hard coding the multiple objects needed to do this – see code below – but how could I do it more flexibly so that I might just give it a couple of arrays of any length and have them save into CoreData (e.g. var animalArray = ["Donkey","Horse","Zebra","Okapi"], var animalCountArray = [7,3,9,2])
import UIKit
import CoreData
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let animal1 = NSEntityDescription.insertNewObject(forEntityName: "ZooAnimals", into: managedContext)
let animal2 = NSEntityDescription.insertNewObject(forEntityName: "ZooAnimals", into: managedContext)
let animal3 = NSEntityDescription.insertNewObject(forEntityName: "ZooAnimals", into: managedContext)
let animal4 = NSEntityDescription.insertNewObject(forEntityName: "ZooAnimals", into: managedContext)
animal1.setValue("Donkey", forKey: "animal")
animal1.setValue(7, forKey: "count")
animal2.setValue("Horse", forKey: "animal")
animal2.setValue(3, forKey: "count")
animal3.setValue("Zebra", forKey: "animal")
animal3.setValue(9, forKey: "count")
animal4.setValue("Okapi", forKey: "animal")
animal4.setValue(2, forKey: "count")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
}

An easy solution is a for loop
let animalArray = ["Donkey","Horse","Zebra","Okapi"]
let animalCountArray = [7,3,9,2]
assert(animalArray.count == animalCountArray.count, "The number of items in the arrays must be equal")
for i in 0..<animalArray.count {
let animal = NSEntityDescription.insertNewObject(forEntityName: "ZooAnimals", into: managedContext)
animal.setValue(animalArray[i], forKey: "animal")
animal.setValue(animalCountArray[i], forKey: "count")
}
do {
try managedContext.save()
} catch {
print("Could not save. \(error)")
}
Side note: guarding AppDelegate is pointless. The app wouldn't even launch if the application delegate class is missing.

Simply you need to use a for loop
let employeeNames = ["Donkey", "Horse", "Zebra","Okapi"]
for i in 0..<employeeNames.count
{
let employeeEntry = NSEntityDescription.insertNewObjectForEntityForName("ZooAnimals", inManagedObjectContext: managedObject)
employeeEntry.setValue(employeeNames[i], forKey: "employeename")
employees.setValue(index, forKey: "animal")
do {
try managedObject.save()
} catch {
print("problem saving")
}
}

Related

function not saving string on textfield to core data

My function below when called is not saving whatever is on the textfield to core data. When appearing in the debugg area what appears is "". THis code when used in the view did load function it does work but when I call it it does not work.
func timTebow(){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Item", in: context)
let newUser = NSManagedObject(entity: entity!, insertInto: context)
newUser.setValue(playName.text, forKey: "atBATS")
do {
try context.save()
} catch {
print("Failed saving")
}
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
for data in result as! [NSManagedObject] {
print(data.value(forKey: "atBATS") as? String)
}
} catch {
print("Failed")
}
}

Using CoreData in swift from a tableview selection

I have 2 functions, one which should save the string to a CoreData attribute and another to fetch it. And this was written by copying working code from elsewhere in the project, so I can't figure out why when I print the contents of 'currentSetting' I get nil.
The save function is called from didSelectRowAtIndexPath and it sends in indexPath.row as the parameter and this fetches a String from an array.
func getImageSetting() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Settings")
do {
let fetcher = try context.fetch(fetchRequest)
let data = fetcher as? [NSManagedObject]
if let results = data {
let settingResult = results[0]
currentSetting = settingResult.value(forKey: "imageQuality") as? String
print(currentSetting as Any)
} else { print ("error") }
}
catch let error as NSError {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
func saveSetting(selection: Int) {
let coreSelection = choices[selection]
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let itemEntity = NSEntityDescription.entity(forEntityName: "Settings", in: managedContext)!
let item = NSManagedObject(entity: itemEntity, insertInto: managedContext)
item.setValue(coreSelection, forKey: "imageQuality")
do {
try managedContext.save()
} catch let error as NSError {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}

Core data not retaining older values

When I save to Core Data and then try to read from it, only the most recently saved value is retained.
The rest are nil when I try to print them out.
In my .xcdatamodeld, my entity is named CD_Cookbook and it has an attribute of name.
I'm not sure what I'm doing wrong.
func newCookbook(cookbook: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "CD_Cookbook", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
item.setValue(cookbook, forKey: "name")
do {
try managedContext.save()
}
catch {
print("did not save cookbook name to core data", error)
}
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "CD_Cookbook")
do {
let cd = try managedContext.fetch(fetchRequest)
print(cd)
}
catch {
print("Failed to fetch cookbook names from Core Data", error)
}
}
Instead of:
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "CD_Cookbook")
Do this instead:
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "CD_Cookbook")

Add Records to Core Data

I want add Records to Core Data but error "Thread 1: signal SIGABRT"
help me
let appDel:AppDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDel.persistentContainer.viewContext
let conchym = NSEntityDescription.insertNewObject(forEntityName: "Muoigiay", into: context)
conchym.setValue("date", forKey: "time10")
conchym.setValue("\(diemdung)", forKey: "dung10")
conchym.setValue("\(diemsai)", forKey: "sai10")
// save to data
do {
try context.save()
} catch {
print("Failed saving")
}

Core Data is saving only last item

I have a function with a entity and a item,and append the value in an array, but it adds only the last item and I think it's because every time I iterate through the array I append the value in the same instance.I can't figure out why.
My function:
func saveItem(itemToSave: String, key: String){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entity(forEntityName: "Recipe", in: managedContext)
let item = NSManagedObject(entity: entity!, insertInto: managedContext)
item.setValue(itemToSave, forKey: key)
do{
try managedContext.save()
recipes.append(item)
}catch{
print("\(error)")
}}
How I call the function:
if let title = self.newRecipeView.titleTextField.text{
saveItem(itemToSave: title, key: "title")
}
First image: https://i.stack.imgur.com/UrLbi.png
Second image: https://i.stack.imgur.com/XjiEP.png
The action when I click the button:
UIView.animate(withDuration: 0.7, delay: 0, options: .curveEaseOut, animations: {
clearView.alpha = 1
self.contentView.isUserInteractionEnabled = false
activityIndicator.startAnimating()
}, completion: { (true) in
if let title = self.newRecipeView.titleTextField.text{
saveItem(itemToSave: title, key: "title")
}
if let category = UserDefaults.standard.object(forKey: "category") as! String?{
saveItem(itemToSave: category, key: "category")
}
if let rating = self.newRecipeView.ratingTextField.text{
saveItem(itemToSave: rating, key: "rating")
}
if let time = self.newRecipeView.timeTextField.text{
saveItem(itemToSave: time, key: "time")
}
if let directions = self.newRecipeView.directionsTextField.text{
saveItem(itemToSave: directions, key: "directions")
}
fetchData()
print(recipes)
activityIndicator.stopAnimating()
_ = self.navigationController?.popToRootViewController(animated: true)
})
Method which save data:
func saveItem(itemToSave: String, key: String){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entity(forEntityName: "Recipe", in: managedContext)
let item = NSManagedObject(entity: entity!, insertInto: managedContext)
item.setValue(itemToSave, forKey: key)
do{
try managedContext.save()
recipes.append(item)
}catch{
print("\(error)")
}
}
Method which fetch data:
func fetchData(){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Recipe")
do{
let results = try managedContext.fetch(fetchRequest)
recipes = results as! [NSManagedObject]
}catch{
print("\(error)")
}
}
Your problem is that you create a new Recipe for every item.
You need to change your function to the following:
func saveItem(title: String, rating: String, category: String, time: String, directions: String){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entity(forEntityName: "Recipe", in: managedContext)
let item = NSManagedObject(entity: entity!, insertInto: managedContext)
recipe.setValue(title, forKey: "title")
recipe.setValue(rating, forKey: "rating")
recipe.setValue(category, forKey: "category")
recipe.setValue(time, forKey: "time")
recipe.setValue(directions, forKey: "directions")
do{
try managedContext.save()
recipes.append(recipe)
}catch{
print("\(error)")
}
}
And then call it by:
saveItem(title: self.newRecipeView.titleTextField.text, rating: self.newRecipeView.ratingTextField.text, category: (UserDefaults.standard.object(forKey: "category") as! String?), time: self.newRecipeView.timeTextField.text, directions: self.newRecipeView.directionsTextField.text)