I have implemented iOS 11 trailingSwipeActionsConfigurationForRowAt and leadingSwipeActionsConfigurationForRowAt for my UITableViewCell. I'm using trailingSwipeActionsConfigurationForRowAt to disable the row, and leadingSwipeActionsConfigurationForRowAt to undo the disable of the row. I've tried to use canEditRowAt, but this disables editing of the entire row. Is there a way to disable only one of the swipe actions instead of disabling the entire row from editing?
I want to disable the undo swipe action if I already swiped to undo, but enable the cancel swipe action. I also want to disable the cancel swipe action if I already swiped to cancel, but enable the undo swipe action.
Try to return the empty array of actions in trailingSwipeActionsConfigurationForRowAt method to disable one sided action.
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let swipeAction = UISwipeActionsConfiguration(actions: [])
return swipeAction
}
Returning nil is sufficient to prevent the swipe action.
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return nil
}
Related
I'm trying to implement two cells, one that can be deleted by swiping, and one that can't be deleted, but has swipe actions the other way.
This is what it looks like now:
I don't want the middle cell to be indented when clicking Edit.
Without any custom code, all cells would show this red circle and get a delete-button, but I have added a few lines of code to prevent that.
This code will set all cells without a leading or trailing swipe action to not become editable, which explains the bottom cell in the gif. I have to include the leading swipe actions to this, because if the cell isn't editable, then I can't swipe at all.
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
let vm = sections[indexPath.section].viewModels[indexPath.row]
return vm.leadingSwipeActions != nil || vm.trailingSwipeActions != nil
}
The following code will prevent the middle cell from showing the red circle.
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return sections[indexPath.section].viewModels[indexPath.row].trailingSwipeActions == nil ? .none : .delete
}
If I don't pass .none for the cell with leading actions, then it would show the red circle AND it would even show a default deletion-swipe. I don't want the ability to delete this row!
How can I prevent the middle cell from indenting, while still retaining the ability to swipe it?
This method seems to work! tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool
https://developer.apple.com/documentation/uikit/uitableviewdelegate/1614873-tableview?language=objc
How can I make a tableviewcell's slide to delete look like the slide to delete for iOS notifications (fade in and don't touch edge of the screen). I will only have the delete button so I don't need multiple buttons. I would like it to delete upon a full swipe just like the notifications.
Here's a photo of the wanted result with 2 buttons (I only want 1):
The current code I have written only sets the editing style to delete. I have tried using UIContextualAction but I believe I can only set the style, background color, and/or image.
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("delete")
}
}
This is what it looks like with my current code:
Try adding a UIView inside the UITableViewCell, with a red background, and a label inside the UIView with the text of delete. Good Luck!
I have a UITableViewCell where I have implemented leadingSwipeActionsConfigurationForRowAt indexPath to allow users to drag right on cells to add them to their favorites. However, in doing so the option for dragging left to delete also appeared. I don't want these cells to be able to be deleted. Is there a way to implement swipe actions without the delete action appearing?
Try this
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return false
}
Edit
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let swipeAction = UISwipeActionsConfiguration(actions: [])
swipeAction.performsFirstActionWithFullSwipe = false // This is the line which disables full swipe
return swipeAction
}
I've been using editActionsForRowAt to create the built-in swipe left functionality to reveal quick-access buttons, like this:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
print("Is this working?")
//Code to create UITableViewRowAction buttons
return [button1, button2]
}
func tableView (_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
//I read I need this, so I have it
return true
}
func tableView (_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
//I read I need this, so I have it
}
Now my whole table, including the swipe, works great. Until...
My editActionsForRowAt function has code where if the user swipes a cell that's expanded (by default they're 50, but users can tap to expand the height) then editActionsForRowAt returns [], an empty array. I do that because I don't want really tall cells showing stretched out buttons.
After that, even after closing, swiping a cell (any cell) doesn't even call editActionsForRowAt. I checked by adding a print-line right at the beginning of that function and it doesn't print no matter what I do after swiping an expanded cell and returning [].
Any ideas on how to fix this?
Instead of returning an empty array from editActionsForRowAt, you should return false from canEditRowAt when a given row isn't editable.
I am trying to learn Swift, but there is a problem in my project that drives me nuts.
I have a working list of data in a ViewController fed by parse.com. I managed to implement a swipe-feature that reveals buttons for both deleting and editing. That is working fine. Now I want the user to be able to reorder the cells. So I successfully implemented a button to put the table into editing-mode. My 2 problems with that are:
When I enter edit-mode I just want to be able to reorder the cells since editing and deleting is done via swipe (via "tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath)". How can I achive that the user doesn't see the 2 buttons for deleting and editing when in editing-mode and touching the delete-circle that is provided automatically?
Is it possible to remove the delete-circle altogether? Using "UITableViewCellEditingStyle.None" also disables the swipe-functionality.
Thanks in advance!
To avoid the round red delete button that appears when you put set UITableView isEditing to true at the left and does nothing when you click it, the minimum that worked for me was this (Swift 4, iOS 11)
// Avoid the round red delete button on the left of the cell:
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .none
}
I also have these functions, which probably interact:
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return savedTempTable.isEditing
}
// Including this function in the delegate enable left-swipe deleting
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
if editingStyle == .delete {
savedConversions.remove(at: indexPath.row)
}
}
// Including this function enables reordering
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath,to destinationIndexPath: IndexPath)
{
let elem = savedConversions.remove(at: sourceIndexPath.row)
savedConversions.insert(elem, at: destinationIndexPath.row)
}
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .none
}
override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
Although people can delete a row through swipe the delete-button in editing mode should not be removed. People may not know about the swipe gesture and by removing the delete button (which they already expect in editing mode) the app becomes more difficult to use.
If you really want to remove the delete button then you have to implement the delegate method tableView(_:editingStyleForRowAtIndexPath:). There you can return .None while the screen is in editing mode and .Delete while the screen is not.
To enable reordering you have to implement the data source methods tableView(_:canMoveRowAtIndexPath:) and tableView(_:moveRowAtIndexPath:toIndexPath:).
You follow this way to remove the delete Icon while editing:
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellAccessoryNone;
}