I have an app that has some form fields. When the form is submitted it writes the data to my Core Data Object. However, when the form is submitted again it overwrites the existing data instead of appending to it, which is what I want to happen instead.
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let userEntity = NSEntityDescription.entity(forEntityName: "User", in: managedContext)
let newUser = NSManagedObject(entity: userEntity! , insertInto: managedContext)
newUser.setValue(titleField, forKey: "title")
newUser.setValue(firstNameField, forKey: "firstName")
newUser.setValue(lastNameField, forKey: "lastName")
newUser.setValue(emailField, forKey: "email")
newUser.setValue(affiliatedOrgField, forKey: "affiliatedOrg")
newUser.setValue(ukRegionField, forKey: "ukRegion")
newUser.setValue(privacyChecked, forKey: "privacyPolicy")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
I have tried using
let userEntity = NSEntityDescription.insertNewObject(forEntityName: "User", into: managedContext)
let newUser = NSManagedObject(entity: userEntity, insertInto: managedContext)
but I get the following error on my 'newUser' constant
Cannot convert value of type 'NSManagedObject' to expected argument type 'NSEntityDescription'
Can anybody help please?
Since you are using NSPersistentContainer you are using at least macOS 10.12 or iOS 10.10. Apple has added some very nice simplifications to Core Data so that it is unnecessary, for example, to use string-based keys which have the disadvantage to being resistant to compiler checking.
The “new Core Data pattern” looks like this:
let managedContext = appDelegate.persistentContainer.viewContext
let newUser = User(context: managedContext)
newUser.title = ...
newUser.firstName = ...
It could be as simple as that. Let me know if it works for you.
You need to keep a reference to your newly created user and then update that user. So do as Tom E suggested
let newUser = User(context: managedContext)
newUser.title = ...
newUser. firstName = ...
Then let newUser be a property in your class of type User or part of an array, [User], depending on your use case
var newUser: User?
When the form gets updated then instead of creating a new user, update the changed properties like
newUser.email = emailField
and call save to persist the update
try managedContext.save()
Cast the object to User:
let newUser = NSEntityDescription.insertNewObject(forEntityName: "User", into: managedContext) as! User
...<fill the fields>
simple way:
let newUser = User(entity: User.entity(), insertInto: managedContext)
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 am following raywenderlich's tutorial for Core Data : Tutorial
the issue I am facing is that in this snippet of code :
let entity = NSEntityDescription.entity(forEntityName: "Person", in: managedContext)!
let person = NSManagedObject(entity: entity,insertInto: managedContext)
The entity value is returned nil and app gets crashed . Is there something that I missed because I have tried 3-4 times but still the same issue
If you say what you say is correct (crashing on the mentioned line) then the Person entity does not exist in the data model.
Please verify that the person exists in the model:
Also following the linked tutorial I suspect you're calling the save method, like so:
func save(name: String) {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
// 1
let managedContext =
appDelegate.persistentContainer.viewContext
// 2
let entity =
NSEntityDescription.entity(forEntityName: "Person",
in: managedContext)!
let person = NSManagedObject(entity: entity,
insertInto: managedContext)
// 3
person.setValue(name, forKeyPath: "name")
// 4
do {
try managedContext.save()
people.append(person)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
Which suggests that you'll also have to check for the name attribute on the Person entity:
I hope this helps you.
This question already has answers here:
How do you update a CoreData entry that has already been saved in Swift?
(15 answers)
Closed 5 years ago.
In my entity i have 5 attributes and some values are already saved, i cannot search specific value from saved data and update the data and save it.
Data 1
name = Conc;
url = "http://192.168.1.12/snapshot";
ipaddress = "http://192.168.1.102";
pass = we;
prof = "Profile_1";
user = web;
Data 2
name = P1;
url = "http://192.168.1.150/hello";
ipaddress = "http://192.168.1.112";
pass = hello;
prof = "Profile_1";
user = web;
All this is saved in my core data i wanted to search the name P1 and replace the data which user adds into the text field and update it.
but it adds as a new entry into the core data.
code used to save the data:
var coreDataIpAddress: [NSManagedObject] = []
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
// 1
let managedContext =
appDelegate.persistentContainer.viewContext
// 2
let entity =
NSEntityDescription.entity(forEntityName: "Data",
in: managedContext)!
let Data = NSManagedObject(entity: entity,
insertInto: managedContext)
// 3
cameraData.setValue(ipAddress, forKey: "ipaddress")
cameraData.setValue(snapshotUrl, forKey: "url")
cameraData.setValue(cameraName, forKey: "name")
cameraData.setValue(userName, forKey: "user")
cameraData.setValue(password, forKey: "pass")
cameraData.setValue(profileToken, forKey: "prof")
// 4
do {
try managedContext.save()
saveCameraDetails.append(Data)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
Every time this line of code executes:
let Data = NSManagedObject(entity: entity,
insertInto: managedContext)
...you are telling Core Data to create a new instance. That's why you get new entries, because you keep creating them. If you want to update an existing instance, you need to get the existing instance instead of creating a new one. Usually you do this with an NSFetchRequest. Apple provides detailed documentation with sample code that explains this.
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