Before deleteData() method was called, I've verified that there are two instances in my Core Data. Now I need to delete one away. I referred to this tutorial to delete my core data.
I managed to copy the first NSManagedObject instance through let person = people[0] as! NSManagedObject through this code, but app terminated on this line managedContext.delete(person).
The error faced was Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObjectContext delete:]: unrecognized selector sent to instance 0x7fefe28092e0'
func deleteData() {
var people = [Particulars]()
let fetchRequest = NSFetchRequest(entityName: "Particulars")
let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDel.managedObjectContext
do {
people = try managedContext.executeFetchRequest(fetchRequest) as! [Particulars]
do {
let person = people[0] as! NSManagedObject
managedContext.delete(person)
try managedContext.save()
} catch let error as NSError {
print("Could not delete data \(error)")
}
} catch let error as NSError
{
print("Could not fetch data \(error)")
}
}
The proper call is not delete, but deleteObject for NSManagedObjectContext.
Also note that it is more readable to write person.first rather than people[0], but it is of course a matter of taste.
I think let person = people[0] as! NSManagedObject is problematic, because
It is not safe and would crash if there are no search results. Use if let person = people.first...
The downcast from Particulars to NSManagedObject also does not make sense. You have already performed a cast when getting the search results.
Related
I'm reading Delete/Reset all entries in Core Data?.
If I follow the steps below, I get an unexpected result:
Call the code below
Then query an entity in the simulator, I will get an entity back!!!
If I call clearCoreDataStore again (or do a restart), only then the value won't be retrieved from core-data
What am I missing?
func clearCoreDataStore() {
let entities = dataManager.persistentContainer.managedObjectModel.entities
for entity in entities {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity.name!)
let deleteReqest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try context.execute(deleteReqest)
} catch {
print(error)
}
}
dataManager.saveContext()
}
The objects being deleted from the persistent store are probably also in an in-memory object context. If so, that memory context must first be updated to reflect the deletions. A thorough discussion can be found here.
In a nutshell...
deleteRequest.resultType = NSBatchDeleteRequestResultType.resultTypeObjectIDs
let result = try context.execute(deleteRequest) as? NSBatchDeleteResult
let objectIDArray = result?.result as? [NSManagedObjectID]
let changes = [NSDeletedObjectsKey : objectIDArray]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [context])
I am reading bunch of objects from core data store , when I am trying to read object from this array in later part of code Xcode asserts for wrong thread access on that statement. I have added -com.apple.CoreData.ConcurrencyDebug 1 flag to the scheme to find out issues related to core data concurrency . When I remove this flag everything works fine.
Here is how I read the data from core data store
let managedContext =
appDelegate.persistentContainer.newBackgroundContext()
//setup request to load persons ( cached contacts)
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "Person")
fetchRequest.fetchBatchSize = 20
//read entties
managedContext.performAndWait {
do {
self.people = try managedContext.fetch(fetchRequest)
print("\(self.people.count) contacts retrieved from cache(CD)" )
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
And I am reading the array from other part of code as below
let tempContact = self.people[index]
var property = tempContact.value(forKey: "firstName") as! String
I get assertion on second line above. The above code resides inside a function which I have tried calling as below
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let moc = appDelegate.persistentContainer.viewContext
let privateMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateMOC.parent = moc
privateMOC.perform {
self.updateChangedContacts()
}
self.contactsTableView.reloadData()
If I simply call updateChangedContacts directly it works , but if I have large number of contacts this operation is going to take significant time blocking main UI.
I want to avoid that , how can i approach this ?
I am working on an app written in Swift that uses Core Data. For it to work correctly, I need to delete all the objects in Core Data for a specific entity and key. I have been able to find many different questions covering deleting from core data, but as far as I can tell none of them only delete objects for a specific key.
My current code follows a similar style to the "Fetch, Delete, Repeat" method in this article. It talks about an iOS 9 updated way to do this with NSBatchDeleteRequest, but I have not discovered any way to make either of these only delete the values for a specific key.
Current Delete Code (I have tried to add a key to the object, but it throws an error about not being able to cast NSCFNumber to NSManagedObject at runtime)
getContext().delete(object.value(forKey: key) as! NSManagedObject)
Full Code Pertaining to Core Data
func getContext () -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
func coreDataReplaceValue(entity: String, key: String, value: Int) {
let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: entity)
do {
let searchResults = try getContext().fetch(fetchRequest)
for object in searchResults as! [NSManagedObject] {
getContext().delete(object.value(forKey: key) as! NSManagedObject)
}
} catch {
print("Error with request: \(error)")
}
let context = getContext()
let entity = NSEntityDescription.entity(forEntityName: entity, in: context)
let accelerationLevel = NSManagedObject(entity: entity!, insertInto: context)
accelerationLevel.setValue(value, forKey: key)
do {
try context.save()
print("saved!")
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
} catch {
}
}
Other questions I have looked at that pertain to my question, but don't include a way to add a key:
Swift 3 Core Data Delete Object
delete core data managed object with Swift 3
This last one looked promising at first, but the code changes it into an NSManagedObject, so I don't think it holds the solution.
Deleting first object in Core Data (Swift)
Thanks for any help!
Taylor
I am trying to implement CoreData with my existing swift project. I followed this tutorial and implemented it with UITableView.
The data is getting added contentiously to the data model (from another view controller) when I am fetching data model record (in another view controller).
Problem
Navigating to the View Controller with UITableView, shows data from data model once. Tapping on the tableView or sliding it up or down causing the application to crash with error
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Entity name must not be nil.'
Function for saving record :
func saveData(date: String, usr : String, piid: String, healthD:String, temp:String, humd:String) {
//1
let managedContext = DataController().managedObjectContext
//2
let entity = NSEntityDescription.entityForName("Hygeine",
inManagedObjectContext:managedContext)
let health = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
//3
health.setValue(date, forKey: "date")
health.setValue(healthD, forKey: "health")
health.setValue(temp, forKey: "temp")
health.setValue(humd, forKey: "humd")
health.setValue(piid, forKey: "pi_id")
health.setValue(usr, forKey: "usr")
//4
do {
try managedContext.save()
//5
healthData.append(health)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
ViewWillAppear for ViewController with UITableView :
override func viewWillAppear(animated: Bool) {
let managedContext = DataController().managedObjectContext
//2
let fetchRequest = NSFetchRequest(entityName: "Hygeine")
//3
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
healthData = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
There are a lot of Objective-C solution to this problem but how to solve it in Swift 2. What I am doing wrong here ?
entityForName returns an optional that you are force unwrapping. That is most likely your error and easily caught in the debugger.
Is your entity name entered wrong? Check it against your model.
And as others have said, learn NSFetchedResultsController, while it won't solve this error, it is easier to work with when dealing with a UITableViewController.
With swift 2.1 and CoreData, I want to delete all data of my database.
with following way, it works well
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let request = NSFetchRequest(entityName: "UserCourse")
let arr = try! context.executeFetchRequest(request)
for item in arr{
context.deleteObject(item as! NSManagedObject)
try! context.save()
}
but i heard that there is a better way to do that with
NSBatchDeleteRequest
here is the code
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let model = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectModel
let delete = NSBatchDeleteRequest(fetchRequest: NSFetchRequest(entityName: "Data"))
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
try! coordinator.executeRequest(delete, withContext: context)
but it raise an error said
2015-12-10 01:36:21.195 test[1090:40088] CoreData: error: Illegal attempt to save to a file that was never opened. "This NSPersistentStoreCoordinator has no persistent stores (unknown). It cannot perform a save operation.". No last error recorded.
2015-12-10 01:36:21.202 test[1090:40088] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores (unknown). It cannot perform a save operation.'
I wonder there must be something wrong with the model or coordinator, but I can't figure out how to get a correct coordinator instance, someone can help me?
This line:
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
creates a new persistentStoreCoordinator, associated with your model, but does not link it to a persistentStore. Hence the error message.
I suspect actually need to use the existing persistentStoreCoordinator associated with your context:
let coordinator = context.persistentStoreCoordinator