I work on an iOS App application that stores some data in Core Data. I found a problem when I had to delete specific data from Core Data.
Although it says that the delete was successfull, the number of elements stored are the same.
Can you take a look ?
Here's the code :
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Session")
fetchRequest.returnsObjectsAsFaults = false
do
{
var session = try managedContext.executeFetchRequest(fetchRequest) as! [Session]
managedContext.deleteObject(session.first!)
if session.first!.deleted {
print("Succesfully deleted")
print(session.count)
}
else {
print("Unsuccesfull")
}
} catch {
print("Detele error : \(error)")
}
As #Vadian said, you forgot to save the context.
So let implement it:
do {
try managedContext.save()
} catch let error as NSError {
print(error)
}
Related
I am saving different activities to Core Data. While the app is working i can easily retrieve this data. But after the app I closed the data is gone even if even after I explicitly save it using context.save(). Any ideas why this happens?
private func getContext() -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
func retrieveTestEntity() -> TestEntity? {
let managedContext = getContext()
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "TestEntity")
do {
let result = try managedContext.fetch(fetchRequest) as! [TestEntity]
if result.count > 0 {
// Assuming there will only ever be one Entity in the app.
return result[0]
} else {
return nil
}
} catch let error as NSError {
print("Retrieving user failed. \(error): \(error.userInfo)")
return nil
}
}
func saveActivity(_ activity: Activity) {
let managedContext = getContext()
guard let testEntity = retrieveTestEntity() else { return }
testEntity.activity.append(activity)
do {
print("Saving session...")
try managedContext.save()
} catch let error as NSError {
print("Failed to save session data! \(error): \(error.userInfo)")
}
}
**this is to how to create a login validation form to move from login to next view controller **
**fetching the data from database**
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
**it stores the data**
let managedContext = appDelegate.persistentContainer.viewContext
//it fetches the data
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Details")
**validation code to check it but the condition fails**
do {
let result = try managedContext.fetch(fetchRequest)
for data in result as! [NSManagedObject] {
if ([emailid.text].count != 0 && [password.text].count != 0){
if (emailid.text == data.value(forKey: "emailId") as? String) && (password.text == data.value(forKey: "passWord") as? String){
let secondvc = storyboard?.instantiateViewController(withIdentifier: "loginVcID") as! loginVc
self.navigationController?.pushViewController(secondvc, animated: true)
}
in this condition it is not moving to next view controller
to check another condition
}
else {
self.label.text = "enter a valid data"
}
}
}
**when it fails it goes to catch to show that**
catch
{
print("Failed")
}
}
}
**this code is for registration to save into database**
**to create a database and store the value**
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let detailEntity = NSEntityDescription.entity(forEntityName: "Details", in: managedContext)!
** creation of database**
let detail = NSManagedObject(entity: detailEntity, insertInto: managedContext)
detail.setValue(username.text, forKeyPath: "userName")
detail.setValue(emailid.text, forKey: "emailId")
detail.setValue(password.text, forKey: "passWord")
detail.setValue(city.text, forKey: "city")
**saving the data**
do {
try managedContext.save()
}
** it display whatever in that method**
catch let error as NSError
{
its shows error when it fails
print("Could not save. (error), (error.userInfo)")
}
Go to you appDelegate, you will find a line // MARK: - Core Data stack & // MARK: - Core Data Saving support, remove the saveContext() function & also remove persistentContainer.. Then
Add this class to your project
final class PersistenceManager {
private init() {}
static let shared = PersistenceManager()
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "ProjectNAME")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
lazy var context = persistentContainer.viewContext
// MARK: - Core Data Saving support
func save() {
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
func fetch<T: NSManagedObject>(_ objectType: T.Type) -> [T] {
let entityName = String(describing: objectType)
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
do {
let fetchedObjects = try context.fetch(fetchRequest) as? [T]
return fetchedObjects ?? [T]()
} catch {
return [T]()
}
}
func deleteAll<T: NSManagedObject>(_ objectType: T.Type) {
let entityName = String(describing: objectType)
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try persistentContainer.persistentStoreCoordinator.execute(deleteRequest, with: context)
} catch {
print(error.localizedDescription)
}
}
func delete(_ object: NSManagedObject) {
context.delete(object)
save()
}
}
To fetch data
PersistenceManager.shared.fetch(User.self)
To delete data
PersistenceManager.shared.delete(user)
To create user
let newUser = Users(context: PersistenceManager.shared.context)
newUser.name = "Zero Cool"
newUser.password = "qwerty"
PersistenceManager.shared.save()
My code is trying to delete a element from a set via button. When the user presses the button the set is deleted from that page but if it is reloaded the code is still there. So it is not permanently deleted. All I am doing is trying to delete a element from the core data set. I save the code in one class and iand display it through another. Link to git https://github.com/redrock34/core-Data-Delete/blob/master/photography%202.zip.
extension ViewController : datacollectionProfotocol {
func deleteData(indx: Int) {
block.reloadData()
let date = users[indx]
users.remove(at: indx)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")
request.predicate = NSPredicate(format:"atBATS = %#", date as CVarArg)
let result = try? context.fetch(request)
let resultData = result as! [NSManagedObject]
for object in resultData {
context.delete(object)
}
do {
try context.save()
print(" saved!")
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}}
My code is trying to delete a elememnt from a set via button. When the button is pressed a runtime error occurs. The error states "Thread 1: Fatal error: Index out of range" at let date = users[indx]. All I am doing is trying to delete a element from the core data set. I save the code in one class and iand display it through another. Link to git https://github.com/redrock34/core-Data-Delete.
extension ViewController : datacollectionProfotocol {
func deleteData(indx: Int) {
users.remove(at: indx)
block.reloadData()
let date = users[indx]
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")
request.predicate = NSPredicate(format:"atBATS = %#", date as CVarArg)
let result = try? context.fetch(request)
let resultData = result as! [NSManagedObject]
for object in resultData {
context.delete(object)
}
do {
try context.save()
print(" saved!")
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
}
How to delete all data for example from an attribute <name>, not Entity, from attribute. I have an entity name - Users, attribute - name and I don't know how to delete all data from an attribute.
for delete the all data you can use this function
func deleteAllData(entity: String) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try managedContext.executeFetchRequest(fetchRequest)
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
managedContext.deleteObject(managedObjectData)
print("Deleted")
}
} catch let error as NSError {
print(error)
}
}
and after that call the function like this
deleteAllData(entity: "your Entity name")
You have to set that attibute to nil and save the context. This is how you have to remove the attribute from entity. You can't delete it like how an entity is deleted from coreData.
I just renewed Rahuld and Piet.t code for Swift and it works.
func deleteAllData(entity: String) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedObjectContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try managedObjectContext.fetch(fetchRequest)
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject
managedObjectContext.delete(managedObjectData)
print("Deleted")
}
} catch let error as NSError {
print(error)
}
try? managedObjectContext.save()
self.fetch(entity: "ListItem")
}
and after that call the function like this
deleteAllData(entity: "your Entity name")
in addition after you need to show the result so you will fetch your data again.
the below function can be used for it
func fetch(entity: String) {
//Veritabanındaki bilginin ekrana gelmesi için veriyi çekme işlemi
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let managedObjectContext = appDelegate?.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>.init(entityName: entity)
data = try! managedObjectContext!.fetch(fetchRequest)
tableView.reloadData()
}
use it like:
self.fetch(entity: "your entity name")
or like this:
fetch(entity: "your entity name")