Swift: Saving Multiple Images to Core Data - swift

I have a Recipe entity with a one-to-many relationship to RecipeImage. The problem I'm having is how to properly save multiple images. What I'm trying to do is once I selected the images, I store them in a tempImageArray. Once I select "Done" I try to convert images within tempImageArray into an array of data since Core Data only accept images as Binary Data. I then set my recipe.images as that array of data.
Currently, I'm only able to save 1 photo instead multiple.
I think im close to the solution but just needs some guidance. Any help you be much appreciated!
class ListDetailViewController: UITableViewController {
var recipeToEdit: Recipe?
var recipeImages = [RecipeImage]()
//image collection
var tempImageArray = [UIImage]()
private func createRecipe() {
let context = CoreDataManager.shared.persistentContainer.viewContext
let recipe = NSEntityDescription.insertNewObject(forEntityName: "Recipe", into: context) as! Recipe
recipe.setValue(textField.text, forKey: "name")
let image = NSEntityDescription.insertNewObject(forEntityName: "RecipeImage", into: context) as! RecipeImage
for i in tempImageArray {
image.imageData = i.jpegData(compressionQuality: 0.8)
recipeImages.append(image)
}
recipe.images?.setValue(recipeImages, forKey: "images")
image.recipe = recipe
do {
try context.save()
//Perform save
navigationController?.popViewController(animated: true)
self.delegate?.didAddRecipe(recipe: recipe)
} catch let saveErr {
print("Failed to save recipe", saveErr)
}
}

Related

save increase int as multiple core data entities

In my swift code below I am trying to save ints to core data. Every time a user hits a button a new int is created. So if the user hits the button twice there are know 2 int entities in core data. My code below is having a runtime error and I dont know how to solve it.
pic
var pageNumber = 0
var itemName : [NSManagedObject] = []
func enterData() {
let appDeldeaget = UIApplication.shared.delegate as! AppDelegate
let context = appDeldeaget.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Player", in: context)
let theTitle = NSManagedObject(entity: entity!, insertInto: context)
theTitle.setValue(pageNumber, forKey: "positon")
do {
try context.save()
itemName.append(theTitle)
pageNumber += 1
}
catch {
}
self.theScores.reloadData()
positionTextField.text = ""
positionTextField.resignFirstResponder()
}
You are introducing a few complications that might be causing the issue.
First, if I understood your purpose, the itemName should not be an array of NSManagedObject, but rather an array of Player. Also, creating the theTitle can be simplified.
Try this instead of the code you proposed:
var pageNumber = 0
// If I understand correctly, you should have an array of Players
var itemName : [Player] = []
func enterData() {
let appDeldeaget = UIApplication.shared.delegate as! AppDelegate
let context = appDeldeaget.persistentContainer.viewContext
// Simpler way to create a new Core Data object
let theTitle = Player(context: context)
// Simpler way to set the position attribute
theTitle.position = pageNumber // pageNumber must be of type Int64, otherwise use Int64(pageNumber)
do {
try context.save()
itemName.append(theTitle)
pageNumber += 1
} catch {
// handle errors
}
// rest of the code
}

CoreData - If something exists don't save it, if it doesn't exists then save it

I have a single entity Favourites and it contains values such as id, name but the problem is that it is creating multiple copies of items and I wanted it to only store values if it is unique. How can I do this with Core Data?
Here is my code:
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let newFav = Favourites(context: context)
if let id = self.itemsViewModel.items?.results?[indexPath.item].id {
newFav.id = id
}
if let name = self.itemsViewModel.items?.results?[indexPath.item].name {
newFav.name = name
}
self.saveItem()
I do this in an alert and outside of that closure is my saveItem() function everything works but I am trying to save only one item with one id. I am thinking of checking if that id exists but I am not quite sure how would I do that with CoreData
func saveItem() {
do {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
try context.save()
} catch {
print("Error saving context \(error)")
}
}
Perform a fetch with a distinct predicate and create a new record if the result is zero, for example
func saveItem(with id : Int32, name : String) {
do {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request : NSFetchRequest<Favourites> = Favourites.fetchRequest()
request.predicate = NSPredicate(format: "id == %d AND name == %#", id, name)
let numberOfRecords = try context.count(for: request)
if numberOfRecords == 0 {
let newFav = Favourites(context: context)
newFav.name = name
newFav.id = id
try context.save()
}
} catch {
print("Error saving context \(error)")
}
}

use uitextfield delegetate to fetch coredata binary data by its count number

My swift code saves 3 names to core data entity "username". I want to use uitextfield delegate to pull a specific string. So when the user enters 2 in the textfield. On the label labelName the name jessica Biel should appear. So the user enters a number into a textfield a string appears on the label. If number 1 is enter the 1st NSManagedObject into the core data entity userName. Link to project https://github.com/redrock34/jessicaBiel
import UIKit
import CoreData
class ViewController: UIViewController,uitextfielddele {
#IBOutlet var labelName : UILabel!
#IBOutlet var enterT : UITextField!
// MARK: Variables declearations
let appDelegate = UIApplication.shared.delegate as! AppDelegate //Singlton instance
var context:NSManagedObjectContext!
// MARK: View Controller life cycle methods
override func viewDidLoad() {
super.viewDidLoad()
openDatabse()
}
// MARK: Methods to Open, Store and Fetch data
func openDatabse()
{
context = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Users", in: context)
let newUser = NSManagedObject(entity: entity!, insertInto: context)
let newUser2 = NSManagedObject(entity: entity!, insertInto: context)
let newUser3 = NSManagedObject(entity: entity!, insertInto: context)
saveData(UserDBObj: newUser, UserDBObj2: newUser2, UserDBObj3: newUser3)
}
func saveData(UserDBObj:NSManagedObject,UserDBObj2:NSManagedObject,UserDBObj3:NSManagedObject)
{
UserDBObj.setValue("kim kardashian", forKey: "username")
UserDBObj2.setValue("jessica biel", forKey: "username")
UserDBObj3.setValue("Hailey Rienhart", forKey: "username")
print("Storing Data..")
do {
try context.save()
} catch {
print("Storing data Failed")
}
fetchData()
}
func fetchData()
{
print("Fetching Data..")
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
for data in result as! [NSManagedObject] {
let userName = data.value(forKey: "username") as! String
print("User Name is : "+userName)
}
} catch {
print("Fetching data Failed")
}
}
}
First of all be aware that on each launch of the app the three records are inserted again and again so you'll get a bunch of duplicates.
As the names are apparently not related to any order add an unique identifier like an integer attribute index – or whatever name is reasonable – and then fetch the data with a predicate NSPredicate(format: "index == %ld", Int(enterT.text!) ?? 0).
You have to do that because Core Data saves the objects unordered.

Saving tableview cells

i've tried saving the data of my tableview using core data however i haven't been able to get it to work with the way i've setup my code.
let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell", for: indexPath) as! TaskCell
cell.taskText.text = tasks[indexPath.row].name
cell.taskPriority.image = tasks[indexPath.row].priority
return cell
where tasks is
var tasks = [Task]()
and it looks like this
class Task {
var name = ""
var priority = UIImage()
var priorityInt = Int()
convenience init(priority: UIImage, name: String, priorityInt: Int) {
self.init()
self.name = name
self.priority = priority
self.priorityInt = priorityInt
PriorityInt is used to change the image which determines the priority of the task.
Leja, "Save data from a table view in the CoreData" doesn't make sense but I will try answering by talking about 2 things.
Saving on CoreData
Create your Data Model with your Task model.
Then you will end up having your Task class inheriting from NSManagedObject like this:
import CoreData
import Foundation
class TaskMO: NSManagedObject {
#NSManaged var name: String?
#NSManaged var priority: Int?
}
You will use NSManagedObjectContext to save your entity with the following code:
guard let task = NSEntityDescription.insertNewObjectForEntityForName("Task", inManagedObjectContext: managedObjectContext) as? TaskMO else { return
do {
try managedObjectContext.save()
} catch {
fatalError("Failed to save: \(error)")
}
Show local data on TableView or CollectionView
let managedObjectContext = …
let tasksFetch = NSFetchRequest(entityName: "Task")
do {
let fetchedTasks = try managedObjectContext.executeFetchRequest(tasksFetch) as! [TaskMO]
} catch {
fatalError("Failed to fetch tasks: \(error)")
}
For a huge amount of data, you can even use NSFetchedResultsController
You can read more about, samples and explanation are well documented. apple documentation here.

Core Data Insert one to many with multiples relationships

Good afternoon!
I am using the core date to save the following entity.
Training Program > Activities > Series
When saving the activities within the program, I am using the method.
let programTranningDB = NSEntityDescription.insertNewObject(forEntityName: "ProgramTranningDB", into: self.getContext())
(programTranningDB as! ProgramTranningDB).addToActivities(activities)
do{
try self.getContext().save()
} catch {
print(error)
}
How can I add series into activities?
Can someone help me?
Assuming your model looks a little like this:
A TrainingProgram can have many activities.
An Activity can have many series.
You will add an instance of Series to an Activity in the same way as you add the Activity to a TrainingProgram.
You can use the auto-generated method on Activity of addToSeries(_:)
I usually keep all my data domain logic contained in a class to aid testing and separation of concerns.
class DomainLogic {
var context: NSManagedObjectContext
init(context: NSManagedObjectContext) {
self.context = context
}
func addNewProgram(named: String) -> TrainingProgram {
guard let program = NSEntityDescription.insertNewObject(forEntityName: "TrainingProgram", into: context) as? TrainingProgram else {
preconditionFailure("TrainingProgram should be created here")
}
program.name = named
return program
}
func addNewActivityToProgram(_ program: TrainingProgram) -> Activity {
guard let activity = NSEntityDescription.insertNewObject(forEntityName: "Activity", into: context) as? Activity else {
preconditionFailure("Activity should be created here")
}
program.addToActivities(activity)
return activity
}
func addNewSeriesToActivity(activity: Activity) -> Series {
guard let series = NSEntityDescription.insertNewObject(forEntityName: "Series", into: context) as? Series else {
preconditionFailure("Series should be created here")
}
activity.addToSeries(series)
return series
}
}
Which leads to a simple sequence to create a new Series and add it down the chain.
var context: NSManagedObjectContext!
func createSeries() -> Series {
let logic = DomainLogic(context: context)
let program = logic.addNewProgram(named: "Fatima's Program")
let activity = logic.addNewActivityToProgram(program)
let series = logic.addNewSeriesToActivity(activity: activity)
return series
}
You'll also need logic to recover existing TrainingProgram objects from the database.