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.
Related
I have 2 UITableView (Table-1 & Table-2) at same UIViewController. I want to editing functionality in my Table-2.
I have added tableview datasource method in my view controller as mentioned below: -
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
tableView.beginUpdates()
myArray.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
tableView.endUpdates()
}
}
and both tableview calling this method. So each tableview cells are able to open delete option.
But I want this delete editing option in only Table-2. I want to restrict delete editing option functionality in Table-1.
Please help. Thanks in advance.
You can use this function provided by UITableViewDelegate:
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
Simply implement some logic to check if you want to allow editing at the given indexPath and given tableView and return true if you want editing/deleting and return false if you don't.
Hope this helps!
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)
}
}
})
}
}
I added a custom swipe to share action on my UITableViewCells in my UITableView. My problem is that for some reason it won't even let me swipe the cell. It immediately crashes with this line:
reason: 'attempt to delete row 25 from section 0 which only contains 25 rows before the update'
However, I'm not trying to delete anything! It's a share button not a delete button. Here are the relevant methods I've added:
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let shareAction = UITableViewRowAction(style: .Normal, title: "Share") { (action: UITableViewRowAction, indexPath: NSIndexPath) -> Void in
// Some stuff
}
shareAction.backgroundColor = UIColor.yellowColor()
return [shareAction]
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
}
Why is my table view controller giving me this error when it should have no business attempting to delete anything?
It turns out it was an issue unrelated to the three methods above. My table view controller is a PFQueryTableViewController subclass which has numberOfRowsInSection baked in out of the box. My problem was that I explicitly added that method when I shouldn't have. Therefore it was being called when it shouldn't have been (it's build into the subclass implicitly), resulting in some wonky behavior. I removed my call to numberOfRowsInSection and it worked as it should.
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()
}
}
I am new to swift And programming. Please Anyone Help me for making call in IOS8 using UITabelViewCell left swipe not to delete A Row but to make a call in iPhone using Swift language
If you want to show a Delete or Insert button, you can use the following default functions of UITableView to accomplish that:
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .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
}
}
Although if you want a different custom button, you should have a look at SWTableViewCell at this link: https://github.com/CEWendel/SWTableViewCell