I'm having problems deleting an item from my Core Data, and having looked at lots of other examples and questions - they all say about deleting an NSManagedObject whereas I'm trying to delete the item at the indexPath.row (which is a String).
var itemsArray = [String]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
What would I put in the following function?
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
}
}
Loading items in Core Data
func loadItems() {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Items")
request.returnsObjectsAsFaults = false
do {
let results = try context.fetch(request)
if results.count > 0 {
for result in results as! [NSManagedObject] {
if let product = result.value(forKey: "product") as? String {
self.itemsArray.append(product)
}
}
}
} catch {
print("Error")
}
}
To be able to delete the object you have to use the NSManagedObject as data source
var itemsArray = [Items]()
The loadItems can be reduced to
func loadItems() throws {
let request = NSFetchRequest<Items>(entityName: "Items")
request.returnsObjectsAsFaults = false
itemsArray = try context.fetch(request)
}
Put the do - catch block around the loadItems() call and print the error instance, not a meaningless literal string.
In cellForRow use
let item = itemArray[indexPath.row]
let product = item.product
To delete the item you have to remove it from the data source, then delete the item in the context and then save the context:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let objectToDelete = itemArray[indexPath.row]
itemArray.remove(at: indexPath.row)
context.delete(objectToDelete)
// here add code to save the context
self.tableView.deleteRows(at: [indexPath], with: .fade) // and you have to update the table view
}
}
Related
With the tableview I am trying to delete only one record of the list but with my code it deletes all the userDefault data. how do i delete only one record?
cell.buttonPressed = {
self.recDictionaryId?["\(title)"] = "\(sentence)"
self.pokemonArray.remove(at: indexPath.row)
self.tvPokemon.deleteRows(at: [indexPath], with: .automatic)
let defaults = UserDefaults.standard
defaults.set(self.pokemonArray, forKey: "UserDefSaveDictionary")
defaults.synchronize()
self.tvPokemon.reloadData()
}
I also tried with:
removeObject(forKey: "UserDefSaveDictionary")
but the result is the same
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
objects.remove(at: indexPath.row)
self. deleteItem(indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
func deleteItem(_ index: Int) {
let userDefaults = UserDefaults.standard
if let data = userDefaults.data(forKey:”keyName”) , var array = try? JSONDecoder().decode([Model].self, from: data) {
array.remove(at: index)
guard let result = try? JSONEncoder().encode(array) else { return }
userDefaults.set(result, forKey:”keyName”)
}
}
you have to fetch the UserDefaults response array and convert it to a model then it would be much easier, if you want make this better you can try by adding a completion block to deleteItem() function and inside that you can perform real deletion
So I'm trying to implement a swipe delete of my favorite items off the favorites tab. The swipe implementation works but when I go back to the Favorites Tab, the item deleted reappears. I'm using core data and I know it is not deleting it from core data but not sure how to fix it. This is my file for the favorites tab:
import UIKit
import CoreData
class FavAnimeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
var favorites = [NSManagedObject]()
var numAnime = 0
var managedObjectContext: NSManagedObjectContext!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
// Do any additional setup after loading the view.
}
//loads every time view appears
override func viewDidAppear(_ animated: Bool) {
load()
}
func load() {
//1
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
//2
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "Favorite")
//3
do {
favorites = try managedContext.fetch(fetchRequest)
tableView.reloadData()
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return favorites.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FavTableViewCell") as! FavTableViewCell
let favAnime = favorites[indexPath.row]
cell.favtitleLabel.text = favAnime.value(forKeyPath: "title") as? String
cell.favsumLabel.text = favAnime.value(forKeyPath: "synopsis") as? String
if let poster = favAnime.value(forKey: "poster") as? String{
let posterUrl = URL(string: poster)!
cell.favposterView.af.setImage(withURL: posterUrl)
}
return cell
}
//MARK: Delete favorite items
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
favorites.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
}
if any can help that be great
The changes (in this case Delete) wont be seen affected until you save the state of the NSManagedObjectContext, Helpfully, managed object context has a matching delete() method that will delete any object regardless of its type or location in the object graph. Once an object has been deleted from the context, we can then call saveContext() to write that change back to the persistent store so that the change is permanent.
do {
try managedObjectContext.save()
} catch (let error) {
print(error.localizedDescription)
}
Remember: you must call saveContext() whenever you want your changes to persist.
I Hope I Helped!
Core Data | nsmanagedobjectcontext
Delete from CoreData
func deleteParticularRecord(id:String){
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// use predicate for delete particular record from coredata.
let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "EnitityName")
let predicate = NSPredicate(format: "id = '\(id)'")
fetchRequest.predicate = predicate
let objects = try! context.fetch(fetchRequest)
for obj in objects {
context.delete(obj as! NSManagedObject)
}
do {
try context.save() // <- remember to put this :)
} catch {
// Do something... fatalerror
}
}
// Call
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
favorites.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
// use id or object id
deleteParticularRecord(id: "_Id_")
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
// Hope its works :)
I got an array that populates a tableview, it works fine when I run the app.
I created a popover with a PickerView to choose one option to sort the TableView data.
I get the user choise in the popover, pass it to the main ViewController, sorted the data and called tableview.reloadData() but nothing happens.
I printed the array after the sort and the array is sorted but I can't saw the changes.
But if I go to other ViewController and came back the data is changed.
Why the changes are not showing when I call the tableview.reloadData().
Here's the code:
var dataModel = DataModel()
var ordenacao = String()
override func viewWillAppear(_ animated: Bool) {
dataModel.loadData()
tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
ordenadados(ordem: ordenacao)
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell! = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")
cell.textLabel?.text = dataModel.notas[indexPath.row].titulo
cell.detailTextLabel?.text = dataModel.notas[indexPath.row].datafinal
print("Ordena Tableview")
for nota in dataModel.notas {
print (nota.titulo ?? "")
}
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataModel.notas.count
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
dataModel.notas.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath as IndexPath], with: UITableViewRowAnimation.fade)
dataModel.saveData()
}
EDIT:
func ordenadados(ordem: String){
dataModel.loadData()
if(ordenacao == "Titulo Asc."){
print("Titulo Asc")
dataModel.notas.sort { $0.titulo! < $1.titulo! }
}else if(ordenacao == "Titulo Desc."){
print("Titulo Desc.")
dataModel.notas.sort { $0.titulo! > $1.titulo! }
}
dataModel.saveData()
for nota in dataModel.notas {
print (nota.titulo ?? "")
}
dataModel.loadData()
tableView.reloadData()
}
In the output the array was sorted but in the TableView nothing changed.
Save and Load Data methods:
//save data
func saveData() {
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWith: data)
archiver.encode(notas, forKey: "teste")
archiver.finishEncoding()
data.write(toFile: dataFilePath(), atomically: true)
}
//read data
func loadData() {
let path = self.dataFilePath()
let defaultManager = FileManager()
if defaultManager.fileExists(atPath: path) {
let url = URL(fileURLWithPath: path)
let data = try! Data(contentsOf: url)
let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
notas = unarchiver.decodeObject(forKey: "teste") as! Array
unarchiver.finishDecoding()
}
}
PLease help me out
Here is my code
//
import UIKit
import CoreData
class SavedPageViewController: UIViewController, UITableViewDataSource, UITableViewDelegate , NSFetchedResultsControllerDelegate {
#IBOutlet weak var tableView: UITableView!
var tableTitleArray = [String]()
var tableDetailArray = [String]()
var tableTypeArray = [String]()
var tableHoursArray = [String]()
var tableImageArray = [NSData]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewWillAppear(animated: Bool) {
// core data - show
let appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context:NSManagedObjectContext = appDel.managedObjectContext
var request = NSFetchRequest(entityName: "SavedIdea")
request.returnsObjectsAsFaults = false;
do {
var result:NSArray = try context.executeFetchRequest(request)
if (result.count > 0) {
self.tableTitleArray = result.valueForKey("heading") as! [String]
self.tableDetailArray = result.valueForKey("detail") as! [String]
self.tableTypeArray = result.valueForKey("type") as! [String]
self.tableHoursArray = result.valueForKey("time") as! [String]
self.tableImageArray = result.valueForKey("image") as! [NSData]
}else{
print("0 result appear....error")}
tableView.reloadData()
}catch {
let fetchError = ("returned error is \(error as! NSError)")
print(fetchError)
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableTitleArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")! as! OTPTableViewCell
cell.LabelTitle.text = tableTitleArray[indexPath.row]
cell.LabelDetail.text = tableDetailArray[indexPath.row]
cell.LabelType.text = tableTypeArray[indexPath.row]
cell.LabelHours.text = String(tableHoursArray[indexPath.row])+"h"
if tableImageArray[indexPath.row].length > 0 {
cell.ImgView.image = UIImage(data: tableImageArray[indexPath.row])
}else{
cell.imageWidthConstraints.constant = 0
}
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
let appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context:NSManagedObjectContext = appDel.managedObjectContext
/* let deleterequest = NSFetchRequest(entityName: "SavedIdea")
deleterequest.returnsObjectsAsFaults = false
do {
let savedData = try context.executeFetchRequest(deleterequest)
if savedData.count > 0 {
for result: AnyObject in savedData{
context.deleteObject(result.valueForKey("heading"))
print("NSManagedObject has been Deleted")
}
try context.save() } } catch {}
}
}
i want to delete a complete row from tableview i.e heading,detail,type etc . My entity name is SavedData. I tried few tutorial but they didnt satisfy my needs . when we slide right then delete appear but dont working as i dont know the code.
This way you can delete Data from coredata based on Entity : Here is simple function to delte user entity data from coredata : Hope it helps
//Delete info from Core data
func deleteUserInfo() {
let context = appdelegate.managedObjectContext
let coord = appdelegate.persistentStoreCoordinator
let fetchRequest = NSFetchRequest(entityName: "entityname")
//Here is the field on which u need to chk which record u want to delete just pass here in value ( acutal value) unique key = field in coredata
let predicate = NSPredicate(format: "uniqueKey == %#", "value")
fetchRequest.predicate = predicate
if #available(iOS 9.0, *) {
//You can put condition to delete data accordingly
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try coord.executeRequest(deleteRequest, withContext: context)
}
catch let error as NSError {
//Error handling
}
catch {}
} else {
// Fallback on earlier versions
do {
let users: NSArray = try appdelegate.managedObjectContext.executeFetchRequest(fetchRequest)
//You can put condition to delete data accordingly
for user in users {
appdelegate.managedObjectContext.delete(user)
}
try appdelegate.managedObjectContext.save()
} catch let error as NSError {
//Error handling
}
catch {}
}
}
I hope this will be useful for deleting the particular row using the index position in core data
func tableView(_ tableView: UITableView, commit editingStyle:
UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let requestDel = NSFetchRequest<NSFetchRequestResult>(entityName: "Contacts")
requestDel.returnsObjectsAsFaults = false
do {
let arrUsrObj = try context.fetch(requestDel)
let objectUpdate = arrUsrObj as! [NSManagedObject]
context.delete(objectUpdate[indexPath.row]) // Deleting Object
} catch {
print("Failed")
}
// Saving the Delete operation
do {
try context.save()
print("deleted")
fetch()
} catch {
print("Failed saving")
}
}
We successfully implemented saving and reading from Core Data but we have problems with removing data from Core Data when random cell is deleted.
How to remove data from Core Data when random cell is deleted from tableView??? We typed some code like removing last index from array but it does not work...
2cd Vc
import UIKit
import CoreData
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var item = [NSManagedObject] ()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
}
func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int
{
return item.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let person = item[indexPath.row]
cell.textLabel!.text = person.valueForKey("username") as? String
cell.detailTextLabel?.text = person.valueForKey("passwords") as? String
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
// WHAT TO TYPE HERE TO REMOVE DATA FROM CORE DATA WHEN RANDOM CELL IS DELETED
let context: NSManagedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
do {
try context.save()
} catch _ {
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Users")
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
item = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
I found it working like this
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle {
case .Delete:
// remove the deleted item from the model
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext
context.deleteObject(item[indexPath.row] as NSManagedObject)
item.removeAtIndex(indexPath.row)
do{
try context.save()
}catch{
print("Error, data not saved!")
}
//tableView.reloadData()
// remove the deleted item from the `UITableView`
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
default:
return
}