Core Data is saving only last item - swift

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)

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")

Saving multiple objects for an attribute in CoreData

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")
}
}

CoreData implementation swift 3

I'm having problems implementing coredata in my project. it seems to be able to save but not to fetch. here's the code
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Utente", in: context)
let item = NSManagedObject(entity: entity!, insertInto: context)
var utente: Profilo? = nil
let vc = CustomTabBarController() as UIViewController
let vc1 = LoginController() as UIViewController
// Configure Fetch Request
do {
let request: NSFetchRequest<NSFetchRequestResult> = Profilo.fetchRequest()
let result = try context.fetch(request) as Profilo
utente = result as Profilo
print()
if utente?.type != nil {
if utente?.type == "students"{
print("students")
present(vc, animated: true, completion: nil)
}
if utente?.type == "parents"{
print("parents")
present(vc, animated: true, completion: nil)
}
if utente?.type == "teachers"{
print("teachers")
present(vc, animated: true, completion: nil)
}
} else {
print("variable type empty")
present(vc1, animated: true, completion: nil)
}
} catch {
let fetchError = error as NSError
print(fetchError)
}
i also get the error on the result line:
cannot invoke 'fetch' with an argument list of type (NSFetchRequest)
The syntax is supposed to be
let request: NSFetchRequest<Profilo> = Profilo.fetchRequest()
let result = try context.fetch(request) as! [Profilo] // returns always an array.
Consider that the default initializers CustomTabBarController() and LoginController() won't work.
As we agreed I'm posting my core data functions, they may not be the best way but they work in my project. My entity is called Goals.
// MARK: - Core data funcitons
func loadCoreData(){
goalsArray.removeAll()
//let request = NSFetchRequest<Goals>(entityName:"Goals")
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do{
let fetchRequest : NSFetchRequest<Goals> = Goals.fetchRequest() as! NSFetchRequest<Goals>
let sortDescriptor = NSSortDescriptor(key: "id", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
let result = try context.fetch(fetchRequest)
for result in result {
goalsArray.append(result)
print("Fetched result goaltitle is \(result.goalTitle!)")
}
tableView.reloadData()
print("I've fetched the results")
}
catch {
fatalError("Sthh")
}
}
func countCoreDataObjects()-> Bool{
//let request = NSFetchRequest<Goals>(entityName:"Goals")
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do{
let fetchRequest : NSFetchRequest<Goals> = Goals.fetchRequest() as! NSFetchRequest<Goals>
let result = try context.fetch(fetchRequest)
if result.count == 0 {
return false
} else {return true
}
}
catch {
fatalError("Sthh")
}
}
func saveToCD(object: goalClassForPassing){
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Goals", in: context)
let goal = NSManagedObject(entity: entity!, insertInto: context) as! Goals
goal.goalTitle = object.goalName
goal.id = String(describing:Date())
goal.imagePath = object.imagePath
do {
try context.save()}
catch {
fatalError("couldn't save to core data")
}
goal.id = String(describing: Date())
goalObjectToSaveToCD?.id = String(describing: NSDate())
print(goalObjectToSaveToCD?.goalTitle)
print("Saved \(goal.goalTitle) - \(goal.id) - \(goal.imagePath) to Core Data")
loadCoreData()
}