I am having a small issue with appending my Core Data object to an array. Everything is being saved correctly in Core Data, but when I checked the array, it was empty. The code looks as follows:
func saveQA(question: String, answer: String) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("Card", inManagedObjectContext: managedContext)
let newQA = Card(entity: entity!, insertIntoManagedObjectContext: managedContext)
newQA.question = question
newQA.answer = answer
do {
try managedContext.save()
playerCards.append(newQA)
}
catch {
print("error")
}
}
What seemed to work for me was changing my array from type Card, to type String. Then appending both newQA.question and newQA.answer separately to playerCards. Although I am unsure this is a valid solution. As I am unsure the question and answer will stay linked to each other that way. Any help is great, thank you in advance.
you should add data to you NSMutableArray like this :
playerCards.addObject(newQA)
Related
I'm developing an iOS contacts app. I don't know how to use Core Data but I learned a little bit and was able to create data and display it on a tableview. But now I need some help. I'm looking for code that queries a Contact name in Core Data to check if this contact already exists. If it does, I need to edit this data, if not I need to create this data. Can someone help me?
I'm using this simple code to create data:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Contact", in: context)
let newEventWithTickets = NSManagedObject(entity: entity!, insertInto: context)
var name = contact.name
var email = contact.email
newEventWithTickets.setValue(name, forKey: "name")
newEventWithTickets.setValue(email, forKey: "email")
do {
try context.save()
} catch {
print("Failed saving")
}
An approach that you can consider is using NSPredicate. Essentially, you create conditions (name & email) to check in your managedContext to find entities that much the specific query.
Here is a rough draft on how to approach it:
let fetchRequest = NSFetchRequest<>(entityName: )
fetchRequest.predicate = NSPredicate(format:)
do {
data = try coreDataStack.managedContext.fetch(fetchRequest)
} catch {
print ("Did not fetch")
}
Once you get the data, use a conditional to compare what was inputed and what your query sends back.
I did go through other posts that dealt this issue. But I couldn't find much with regard to my problem. Hope somebody can help. My issue is...I am having a certain edited record that I want to display in my tableview. For that I want to update that entry in Core-Data also. I am not able to figure out how that can be done.
This is how I am bringing the edited data in tableview and saving in Core Data. The updation has to be done somewhere in between but I am not able to figure out exactly how and where..?
#IBAction func saveToMainEditViewController (segue:UIStoryboardSegue) {
let detailViewController = segue.source as! EditCategoriesTableViewController
let index = detailViewController.index
let modelString = detailViewController.editedModel //Edited model has the edited string
let myCategory1 = Category(context: self.context)
myCategory1.categoryName = modelString
mangObjArr[index!] = myCategory1
//Saving to CoreData
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Category", in: managedContext)
let category = NSManagedObject(entity: entity!, insertInto: managedContext)
category.setValue(myCategory1.categoryName, forKeyPath: "categoryName")
category.setValue(myCategory1.categoryId, forKey: "categoryId")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
Steps:
Understand basic concepts
Fetch Record
Update Record
Save context
Concepts:
This is just a crude explanation, the proper explanation is in the link below.
Though it is time consuming, please refer to the link below, it will help you understand CoreData. If you don't understand you will encounter a lot of problems later on.
Entity:
In the core data model you can create entities, these are the tables.
Managed Object:
This is the class representation of the entity
Each instance of this class would represent a single row in the table.
Managed Object Context:
Imagine managed object context like a piece of paper / scratch pad
The managed objects are created / updated / deleted on a specific managed object context.
You can save / discard the changes made to a managed object context.
Not Thread Safe:
When ever you perform anything on a managed object context, make sure you use within context.performAndWait { }. This will ensure that context operations are performed on the context's queue (thread).
Fetch and Update:
func fetch() {
let request : NSFetchRequest< Category> = Category.fetchRequest()
//Predicate builds the where clause to filter records
//This is a sample, so edit based on your requirement
request.predicate = NSPredicate(format: "categoryID = %#", argumentArray: [10])
context.performAndWait {
do {
let categories = try context.fetch(request)
//Update
for category in categories {
category.name = "aaa"
}
}
catch {
print("error = \(error)")
}
}
}
Save:
func save() {
if context.hasChanges {
context.performAndWait {
do {
context.save()
}
catch {
print("Save error: \(error)")
}
}
}
}
Reference:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/index.html
This question already has answers here:
Core Data in Swift: Only saving last object in a for loop
(4 answers)
Closed 6 years ago.
With this function I want to add attributes in core-data entity but it saves only last item repeatedly.
what am I doing wrong?
func SetFeaturedValues(Array : NSArray){
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("FeaturedJob",
inManagedObjectContext:managedContext)
let FeaturedJob = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
print("array is \(Array)")
for i in Array{
if let rowData :NSDictionary = i as? NSDictionary{
FeaturedJob.setValue(rowData["company"], forKey: "company")
FeaturedJob.setValue(rowData["city"], forKey: "city")
FeaturedJob.setValue(rowData["id"], forKey: "id")
FeaturedJob.setValue(rowData["user_logo"], forKey: "user_logo")
FeaturedJob.setValue(rowData["title"], forKey: "title")
do {
try managedContext.save()
self.Featured.append(FeaturedJob)
print("featured job is \(FeaturedJob)")
// people.append(person)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
}
}
Ok, so this could still do with some tidying up but...
What's going wrong is that you are creating only one singleNSManagedObject instance called FeaturedJob. Every time you iterate through the array you append its value and save it. But its the same instance! That's why only one instance gets saved.
So put the line with let let FeaturedJob = ... inside the if block just before you start assigning values. That way you're going to get a new one each time.
PS: You are saving the context with every iteration. You probably only want to do that once at the end of the function.
As title, I have an array of multiple objects and I wish to store them in core data(I understand that we can't save array into core data so I break my code into json[0][i]["ID"].int format), perhaps you will be clearer after reading my code
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext
let newUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObject
socket.on("reply") {data, ack in
let json = JSON(data)
print("database replied")
print(json[0].count)
for var i=0; i<json[0].count; ++i{
newUser.setValue(json[0][i]["ID"].int, forKey: "patientID")
newUser.setValue(json[0][i]["Name"].string, forKey: "patientName")
newUser.setValue(json[0][i]["Mileage"].double, forKey: "patientMileAge")
do{
try context.save()
}catch{
print("Could not save data")
}
}
}
This is what my data would look like
Here comes the troubles, i only get [ID:4, Name:'hung', Mileage:'0.23'] as the result, the former 2 arrays have been replaced.
Why can't I save them as I intended?
let newUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObject
should be inside the loop, because otherwise you create one object and then repeatedly update it and save the change (so the old value is overwritten)
Move this line of code into your loop:
let newUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObject
This should work, write me if it didn't
because you're not adding 3 entries, you're only updating the values for one.
you need to move
let newUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObject
inside your for loop
I am having trouble inserting an element at the first index to CoreData
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("Thing",
inManagedObjectContext:managedContext)
let thing = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
thing.setValue(name, forKey: "name")
thing.setValue(category, forKey: "category")
do {
try managedContext.save()
} catch let error as NSError {
}
How do I insert thing at index 0? Is it possible or do I have to rewrite all the data? Thanks!
You cannot insert a new NSManagedObject at a particular index. The order things are held in the store is for CoreData and SQLite to manage. You should instead ensure that you fetch the objects in the order that you want. This is done by specifying a sort descriptor (NSSortDescriptor) for your fetch request. So if you want things ordered by name, you would use:
let nameSort = NSSortDescriptor(key:"name", ascending:true)
fetchRequest.sortDescriptors = [nameSort]
If you want some other sort order, if necessary add an attribute to your Entity to represent that sort order, and set the appropriate values for each object you create.