'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal - swift

#IBAction func CreateButton(_ sender: AnyObject) {
let appDelegate = (UIApplication.shared.delegate as! AppDelegate)
let managedContext =
appDelegate.persistentContainer.viewContext
let entity =
NSEntityDescription.entity(forEntityName: "EventData",
in: managedContext)!
let newEvent = NSManagedObject(entity: entity,
insertInto: managedContext)
newEvent.setValue( Venuetextfield.text!, forKey: "eventVenue")
newEvent.setValue(Titletextfield.text!, forKey: "eventTitle")
newEvent.setValue(Descriptiontextfield.text!, forKey: "eventDescription")
newEvent.setValue(Datetime, forKey: "eventDateTime")
// sending data to coredata.
(UIApplication.shared.delegate as! AppDelegate).saveContext()
let _ = navigationController?.popViewController(animated: true)
}
Hey guys how can i make entityForName not nil where NSManagedObject is also searching for entity name?
I have also create a NSMangedObject class containing all the entity attributes.
Do I need to link my Model.xcdatamodel id file to view controller class?

You should do like this,
let categoryMaster = NSEntityDescription.insertNewObject(forEntityName: "entity Name", into: managedContext) as! CategoryMaster //Here CategoryMaster is entity class which is the sub class of NSManageObject
categoryMaster.categoryId = NSNumber.init(value: 1)
categoryMaster.categoryIndent = NSNumber.init(value: 2)
categoryMaster.categoryName = textFields.text
categoryMaster.parentCategory = currentCategory.categoryId
categoryMaster.categoryIndex = NSNumber.init(value: 0)
guard (try? managedContext.save()) != nil else
{
fatalError("Something went wrong")
}
You can check out whole tutorial here
Note : This is just an example for how to use core data, you may find some syntax errors

Related

save core data into boolean value

In my swift code below the goal is to save a boolean value into core data. I am getting a compile error stating Thread 1: "Unacceptable type of value for attribute: property = "bool"; desired type = NSNumber; given type = __SwiftValue; value = true.". I don't know what to do next. I also added a photo of my core data attributes. I have 2 classes a base class and a helper class.
pic
class ViewController: UIViewController {
var user : [User]? = nil
CoredataHandler.saveObject(username: "Yahs", password: "213", bool: true)
}
class CoredataHandler : NSManagedObject {
private class func getContext() -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
class func saveObject(username: String,password: String,bool: DarwinBoolean) -> Bool{
let context = getContext()
let entity = NSEntityDescription.entity(forEntityName: "User", in: context)
let managedObject = NSManagedObject(entity: entity!, insertInto: context)
managedObject.setValue(username, forKey: "username")
managedObject.setValue(password, forKey: "password")
managedObject.setValue(bool, forKey: "bool")
do {
try context.save()
return true
} catch{
return false
}
}
}

Resolving core data relationship raising SIGABRT error

I am relearning the swift core data basics using the swift playground.
I am writing out core data long-hand to write a simple playground app where
One Company has many Employees
I am constantly getting an error:
error: Execution was interrupted, reason: signal SIGABRT.
When it comes to saving a relationship between a company and a single employee, but I'm not sure why its being raised.
My code now follows:
// Swift playground code
import CoreData
class NotificationListener: NSObject {
#objc func handleDidSaveNotification(_ notification:Notification) {
print("did save notification received: \(notification)")
}
}
let listener = NotificationListener()
NotificationCenter.default.addObserver(listener, selector: #selector(NotificationListener.handleDidSaveNotification(_:)), name: NSNotification.Name.NSManagedObjectContextDidSave, object: nil)
// Define managed object
let model = NSManagedObjectModel()
//: [Entities]
let companyEntity = NSEntityDescription()
companyEntity.name = "Company"
let employeeEntity = NSEntityDescription()
employeeEntity.name = "Employee"
employeeEntity.indexes = []
//: [Attributes]
let companyNameAttribute = NSAttributeDescription()
companyNameAttribute.name = "name"
companyNameAttribute.attributeType = NSAttributeType.stringAttributeType
companyNameAttribute.isOptional = false
let countryAttribute = NSAttributeDescription()
countryAttribute.name = "country"
countryAttribute.attributeType = NSAttributeType.stringAttributeType
countryAttribute.isOptional = false
let employeeNameAttribute = NSAttributeDescription()
employeeNameAttribute.name = "name"
employeeNameAttribute.attributeType = NSAttributeType.stringAttributeType
employeeNameAttribute.isOptional = false
let ageAttribute = NSAttributeDescription()
ageAttribute.name = "age"
ageAttribute.attributeType = NSAttributeType.integer16AttributeType
ageAttribute.isOptional = false
// Relationships
let companyRelationship = NSRelationshipDescription()
let employeeRelationship = NSRelationshipDescription()
companyRelationship.name = "company"
companyRelationship.destinationEntity = companyEntity
companyRelationship.minCount = 0
companyRelationship.maxCount = 0
companyRelationship.deleteRule = NSDeleteRule.cascadeDeleteRule
companyRelationship.inverseRelationship = employeeRelationship
employeeRelationship.name = "employees"
employeeRelationship.destinationEntity = employeeEntity
employeeRelationship.minCount = 0
employeeRelationship.maxCount = 1
employeeRelationship.deleteRule = NSDeleteRule.nullifyDeleteRule
employeeRelationship.inverseRelationship = companyRelationship
companyEntity.properties = [companyNameAttribute, countryAttribute, employeeRelationship]
employeeEntity.properties = [employeeNameAttribute, ageAttribute, companyRelationship]
model.entities = [companyEntity, employeeEntity]
// Create persistent store coordinator
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel:model)
do {
try persistentStoreCoordinator.addPersistentStore(ofType: NSInMemoryStoreType, configurationName: nil, at: nil, options: nil)
} catch {
print("error creating persistentStoreCoordinator: \(error)")
}
let managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
// Companies
let companyABC = NSEntityDescription.insertNewObject(forEntityName: "Company", into: managedObjectContext)
companyABC.setValue("ABC Ltd", forKeyPath: "name")
companyABC.setValue("United States", forKeyPath: "country")
let companyDelta = NSEntityDescription.insertNewObject(forEntityName: "Company", into: managedObjectContext)
companyDelta.setValue("Delta", forKeyPath: "name")
companyDelta.setValue("Canada", forKeyPath: "country")
let tom = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: managedObjectContext)
tom.setValue("Tom", forKey: "name")
tom.setValue(22, forKey: "age")
tom.setValue(companyABC, forKey: "company") // <<-- Throws error
let sarah = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: managedObjectContext)
sarah.setValue("Sarah", forKey: "name")
sarah.setValue(41, forKey: "age")
sarah.setValue(companyDelta, forKey: "company") // <<-- Throws error
func save(context: NSManagedObjectContext) {
// Save context
do {
try context.save()
} catch {
print("error saving context: \(error)")
}
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Company")
var results: [NSManagedObject] = []
do {
results = try managedObjectContext.fetch(fetchRequest)
print ("\n#\(results.count) records found\n")
} catch {
print("error executing fetch request: \(error)")
}
print("results: \(results)")
}
save(context: managedObjectContext)
The issue comes when it attempts to save one employee:
let tom = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: managedObjectContext)
tom.setValue("Tom", forKey: "name")
tom.setValue(22, forKey: "age")
tom.setValue(companyABC, forKey: "company")
The error is raised when attempting to set the companyABC as the relationship for the tom object.
The objective is to make Tom and employee of companyABC
I believe the relationship has been created properly.
But I am unsure of what is causing the error.
Thus, my query is: How can I resolve this error?
With thanks
...
tom.setValue(Set([companyABC]), forKey: "company")
...
sarah.setValue(Set([companyDelta]), forKey: "company")
...
Because in this case, if you'd generate a class model with XCode from a CoreData Graph, it would have generate the objects where the property company is a (NS)Set. I think it should be written somewhere in the CoreData documentation, but set is unfortunately a too common word. Edit, found it.
From the doc:
The Destination pop-up menu defines what object (or objects) is returned when the relationship is accessed in code. If the relationship is defined as to-one, a single object (or nil if the relationship can be optional) is returned. If the relationship is defined as to-many, a set is returned (or again, nil if the relationship can be optional).

this class is not key value coding-compliant for the key Project1.'

I am new to iOS development , can you help me anyone in bug point of you. thank you for advance.
uncaught exception 'NSUnknownKeyException', reason:
'[ setValue:forUndefinedKey:]:
this class is not key value coding-compliant for the key Project1.'
let context = appdelegate.persistentContainer.viewContext
let proj = Project()
let arrProj = dic.object(forKey: "Projects") as! NSArray
for n in 0..<arrProj.count {
let subDic = arrProj.object(at: n) as! NSDictionary
let item = ProjectItem(dict: subDic)
proj.arrProjs.append( item )
let projects = NSEntityDescription.entity(forEntityName: "Projects", in: context)
projects?.setValue(item.Project, forKey: "project1")
projects?.setValue(item.Project2, forKey: "project2")
projects?.setValue(item.ID, forKey: "projectid")
projects?.setValue(item.radius, forKey: "radius")
projects?.setValue(item.GeofenceType, forKey: "geo_Type")
projects?.setValue(item.Geofence, forKey: "geofence")
projects?.setValue(item.Coordinates, forKey: "coordinates")
}
You should set values in NSManagedObject object, not in NSEntityDescription object
let entity = NSEntityDescription.entity(forEntityName: "Projects", in: context)
for n in 0..<arrProj.count {
let projects = NSManagedObject(entity: entity!, insertInto: context)
projects?.setValue(item.Project, forKey: "project1")
projects?.setValue(item.Project2, forKey: "project2")
//...
}
Please check this using insertobject query you can save your data in core data.
let context = appdelegate.persistentContainer.viewContext
let projects = NSEntityDescription.insertNewObject(forEntityName: "Projects", into: context) as! Projects
projects.project1 = item.Project
projects.project2 = item.Project2
or
projects?.setValue(item.Project, forKey: "project1")
projects?.setValue(item.Project2, forKey: "project2")
projects?.setValue(item.ID, forKey: "projectid")
projects?.setValue(item.radius, forKey: "radius")
do{
try context.save()
}catch{
print("error")
}

Fetching core data issue

I have an array with a SQLite with about 2000 records and all are listed on a tableview. When one of the records are selected, it goes to the "speciesDetailViewController" were it displays details of that item, including the common name of that species.
Currently, all displayed fields are not editable.
I am now adding the ability for the user to to change one of the fields, their common name and the ability to add notes per species.
The minor change is saved in CoreData as I have no experience with SQLite (hired someone).
I am fairly certain the data is being stored as I have print commands showing so.
My issue seems to be retrieving the data.
Note that as editing this field is optional, not every species will have a record in coreData, only the species that the user updated their common name.
class SpeciesDetailData: NSManagedObject
{
#NSManaged var speciesName: String
#NSManaged var commonName: String
#NSManaged var commonForeignName: String
#NSManaged var speciesNote: String
}
.
var speciesDetailData : SpeciesDetailData?
var speciesDataObject: [NSManagedObject] = []
var speciesNameToSave = String()
#IBAction func ckSaveCommonNameButton(_ sender: Any) {
speciesNameToSave = speciesLabel.text!
self.saveSpeciesName(speciesName: speciesNameToSave)
let commonNameToSave = ckCommonNameTextField.text
self.saveCommonName(commonName: commonNameToSave!)
}
func saveCommonName (commonName: String) {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "SpeciesDetailData", in: managedContext)!
let saveEntity = NSManagedObject(entity: entity, insertInto: managedContext)
saveEntity.setValue(commonName, forKey: "commonName")
saveSpeciesName(speciesName: speciesNameToSave)
do {
try managedContext.save()
speciesDataObject.append(saveEntity)
print(commonName)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
func saveSpeciesName (speciesName: String) {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "SpeciesDetailData", in: managedContext)!
let saveEntity = NSManagedObject(entity: entity, insertInto: managedContext)
saveEntity.setValue(speciesName, forKey: "speciesName")
do {
try managedContext.save()
speciesDataObject.append(saveEntity)
print(speciesName)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
Here is the retrieving function
func retrieveCoreDataSpecies () {
let context = (UIApplication.shared.delegate
as! AppDelegate).persistentContainer.viewContext
let entity = NSEntityDescription.entity(
forEntityName: "SpeciesDetailData", in: context)
let request: NSFetchRequest<SpeciesDetailData> = SpeciesDetailData.fetchRequest()
request.entity = entity
let pred = NSPredicate(format: "speciesName = %#", specieDetail.specie)
request.predicate = pred
do {
let results = try context.fetch(request as!
NSFetchRequest<NSFetchRequestResult>)
if (results.count > 0) {
let match = results[0] as! NSManagedObject
if speciesDetailData?.commonName != nil {
ckCommonNameTextField.text = match.value(forKey: "commonName") as? String
} else {
}
if ckNotesTextView.text == "" || ckNotesTextView.text == nil {
} else {
ckNotesTextView.text = match.value(forKey: "speciesNote") as! String
}
}
} catch let error {
print("Count not fetch \(error), \(error.localizedDescription)")
}
}
When it gets to the
if speciesDetailData?.commonName != nil
it thinks the record is empty and skips over the needed lines.
Any help is appreciated
You are creating separate objects in the two save functions. In each case you are setting only one of the properties, so after you call saveSpeciesName you will have created an object with species name set, and after you call saveCommonName you will have created a different object with the common name set. You need to set both the species name and the common name on the same object.

Edit value for core data key for certain id

I have a Core data entity that is made of id and detailText. The idea is that my textfield stores it's content alongside certain id that is a timestamp in my case. Now when the user stores the detailText for the first time it works as it should, but if the user edits the detailText for the specific id, I want to remove the old detailText and put the new detailText.
Basically I need help with writing the query below in Swift/Core data.
UPDATE myEntity SET detailText = theNewDetailText WHERE ID = myID;
These are my current save and replace function, I use predicate to find select my id but I'm having trouble updating the corresponding detailText field for the certain ID.
func saveTextFromTextFieldToCoreData(textToSave: String){
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entityDescription = NSEntityDescription.entityForName("GoalDetail", inManagedObjectContext:managedContext)
let thingToSaveToCD = NSManagedObject(entity: entityDescription!, insertIntoManagedObjectContext: managedContext)
print("received text to store and it's \(textToSave)")
if entityIsEmpty("GoalDetail") == true {
thingToSaveToCD.setValue(data.timeStamp, forKey: "id")
thingToSaveToCD.setValue(textToSave, forKey: "detailText")
print("succesfully saved \(data.timeStamp) and \(textToSave)")
} else {
replaceTheValueFromCoreData()
}
}
func replaceTheValueFromCoreData(){
print("i have entered the delete core data item")
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "GoalDetail")
let predicate = NSPredicate(format: "id == %#", data.timeStamp)
fetchRequest.predicate = predicate
//let entityDescription = NSEntityDescription.entityForName("GoalDetail", inManagedObjectContext:managedContext)
//let thingToSaveToCD = NSManagedObject(entity: entityDescription!, insertIntoManagedObjectContext: managedContext)
do{
let goal = try appDelegate.managedObjectContext.executeFetchRequest(fetchRequest)
try managedContext.save()
}
catch{
//error
}
I've been through google and stack overflow but so far haven't managed to execute this so any help is greatly appreciated.
I've solved it
func saveTextFromTextFieldToCoreData(textToSave: String){
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entityDescription = NSEntityDescription.entityForName("GoalDetail", inManagedObjectContext:managedContext)
let thingToSaveToCD = NSManagedObject(entity: entityDescription!, insertIntoManagedObjectContext: managedContext)
//clumsy named entity is empty returns if there is already
// an ID / data.timeStamp in that entity so that I can
// either save or replace the data
print("received text to store and it's \(textToSave)")
if entityIsEmpty("GoalDetail") == true {
thingToSaveToCD.setValue(data.timeStamp, forKey: "id")
thingToSaveToCD.setValue(textToSave, forKey: "detailText")
print("succesfully saved \(data.timeStamp) and \(textToSave)")
} else {
replaceTheValueFromCoreData()
print("ovo tribq prominiti")
}
}
func replaceTheValueFromCoreData(){
print("i have entered the delete core data item")
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "GoalDetail")
let predicate = NSPredicate(format: "id == %#", self.data.timeStamp)
fetchRequest.predicate = predicate
do {
if let fetchResults = try appDelegate.managedObjectContext.executeFetchRequest(fetchRequest) as? [NSManagedObject] {
if fetchResults.count != 0{
var managedObject = fetchResults[0]
managedObject.setValue(self.trextViewForGoal.text, forKey: "detailText")
try managedContext.save()
}
}}
catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
}