What I have is a table view with different cells that display different messages with other people you're chatting with. Upon swiping the cell to the left, a Delete option shows up. I want to be able to delete both the cell itself as well as the Room associated with it in Parse. This is what I have so far:
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
//Delete messages here
let query = PFQuery(className: "Message")
query.whereKey("Room", equalTo: ??????)
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
tableView.endUpdates()
}
}
This function displays the Delete option, and when I click it, I want it to delete the cell it was clicked in. Does anyone know what goes inside the query? I have a Message class and I want to delete the Room key that's associated with the cell I delete.
Try this :
var dataToDelete:NSMutableArray = [] // this is a dummy array just to replicate your array
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
var object = dataToDelete[indexPath.row] as! PFObject
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
tableView.endUpdates()
object.delete()
}
}
Related
I'm having trouble removing the last cell I have tried tableView.reloadData() and beginUpdate(), endUpadate(), and all these methods works fine if I have more than one cell, but when I come to deleting the last cell it didn't work and the tableView won't reloadData at the same time that I delete the last cell, other cells 2-3-4 no problem, Plus when I close the app everyThing works fine.
im deleting the cells from the firebase store its a document that contains data if concern
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
self.DriverOffers.remove(at: indexPath.row)
self.DriverOrdersTV.deleteRows(at: [indexPath], with: .automatic)
self.DriverOrdersTV.reloadData()
}else if editingStyle == .insert {
self.DriverOrdersTV.beginUpdates()
self.DriverOrdersTV.insertRows(at: [IndexPath.init(row: 0, section: 0)], with: .automatic)
self.DriverOrdersTV.endUpdates()
}
}
Basically to delete the cell "offline" I use this method so that whenever you swipe from right to left the user can delete the tableview cell.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
self.polls.remove(at: indexPath.row)
}
}
However, it obviously doesn't affect the CKRecord of the cell content I created before. So how can I fetch and delete the CKRecord data at the exact row the user swiped-to-delete on?
Assuming polls is the data source array declared as [CKRecord] you have to do three things.
Get the record from the data source array at the given index and remove it from the appropriate CKDatabase.
Remove the record from the data source array (you're already doing that).
Delete the row in the table view calling deleteRowsAtIndexPaths passing [indexPath].
For example (publicDatabase is the actual CKDatabase instance):
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
let record = polls[indexPath.row]
publicDatabase.deleteRecordWithID(record.recordID, completionHandler: ({returnRecord, error in
// do error handling
})
polls.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
Edit:
For proper error handling you might have to put the code of step two and three into the completion block.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
let record = polls[indexPath.row]
publicDatabase.deleteRecordWithID(record.recordID, completionHandler: ({returnRecord, error in
if error != nil {
// do error handling
} else {
self.polls.removeAtIndex(indexPath.row)
dispatch_async(dispatch_get_main_queue()) {
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
})
}
}
My TableView contains multiple sections. Now when I click "delete" for the row selected, it deleted the row in upper section. How to fix this?
I guess the Index for the row to delete in not correct, but I am not sure and have no idea how to fix it. This is my code:
var sectionTitles = [String]()
var savedURLs = [[String]]()
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
savedURLs.removeAtIndex(indexPath.row)
NSUserDefaults.standardUserDefaults().setObject(savedURLs, forKey: Key_SavedURLs)
savingTableView.reloadData()
}
}
NSIndexPath identifies both the row as well as the section of the cell. You need to check the indexPath.section and the indexPath.row to know which item in your savedURLs was deleted.
I am trying to remove a item from my TableView but when I swipe to left and click in Delete, I got this error:
This is the code that I have, when I comment the self.tableView.deleteRowsAtIndexPaths line, everything works fine for me.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
if let index: NSIndexPath = indexPath {
self.tableView.beginUpdates()
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
self.configurations.delete(ProductDatabase.deleteProduct(self.products[index.row]))
loadProductsToListOrder()
self.tableView.endUpdates()
}
} 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
}
}
I searched and found here on stack overflow about this beginUpdates and endUpdates.
Thank you.
Update
loadProductsToListOrder function
func loadProductsToListOrder() {
self.products = ProductDatabase.listProduct(self.configurations.db!)
self.tableView.reloadData()
}
If I have one element in my TableView, I do not have this problem. Just happen if I have more than one itens in my TableView.
Update 2
The answer that #harshayarabarla gave works for me, because I was forgetting to add the self.products.removeAtIndex(indexPath.row) before the deleteRowsAtIndex.
Thanks!
You need to remove the object from your datasource of the table view before you perform self.tableView.deleteRowsAtIndexPaths. later you can call self.tableView.reloadData method instead of begin updates and end updates. It's not necessary to call reloadData method though, as self.tableView.deleteRowsAtIndexPaths takes care of reloading thing.
if you call self.tableView.deleteRowsAtIndexPaths before making changes to dataSource of the table view you might face this error.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
if let index: NSIndexPath = indexPath {
self.configurations.delete(ProductDatabase.deleteProduct(self.products[index.row]))
self.products.removeAtIndex(index.row)
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
loadProductsToListOrder() // you can comment this if you are not adding any new items to products array
}
} 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
}
}
See Delete Data from Coredata Swift for full history.
override 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(myData[indexPath.row] as NSManagedObject)
myData.removeAtIndex(indexPath.row)
context.save(nil)
//tableView.reloadData()
// remove the deleted item from the `UITableView`
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
default:
return
}
}
Also need was these two lines of code to be corrected.
var myData: Array<AnyObject> = []
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext
I need to create a action in editActionsForRowAtIndexPath to delete a row in a table. Following some research on the internet I came to this code:
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let remove = UITableViewRowAction(style: UITableViewRowActionStyle.Destructive, title: "Remover", handler: { (action: UITableViewRowAction, indexPath: NSIndexPath) -> Void in
self.tableData.removeObjectAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
})
return [remove]
}
but now I get this error
UITableView internal bug: unable to generate a new section map with
old section count: 1 and new section count: 0
When you delete a row from UITableView, you need to take care of two things.
First you should call tableView.deleteRowsAtIndexPaths only after you remove the object from the data source already. Because it'll check for the count again and ensure that the resultant data source have one less value.
Now the second thing to remember is that the no. of section can't be 0 after you delete the last row. If you are returning 0 to numberOfSectionsInTableView, return 1 at least on empty row count. Another option is to actually delete the index too when you delete the last row.
You don't need to use 'editActionsForRowAtIndexPath' method unless you implement your own custom accessory view but other wise you can use the standard swipe left gesture to delete rows and the delegate called is commitEditingStyle
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
tableData.removeObjectAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
else if editingStyle == .Insert {
//edit cell
}
}
//change the default 'Delete' text
override func tableView(tableView: UITableView, titleForDeleteConfirmationButtonForRowAtIndexPath indexPath: NSIndexPath) -> String? {
return "Show this instead of delete"
}
Do deleteRowsAtIndexPaths or reloadData, but not both.