How to disable trailing swipe on UITableView Swift? - swift

How to ignore the right to left swipe or the Trailing swipe, does anyone know how to accomplish this?

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let swipeAction = UISwipeActionsConfiguration(actions: [])
return swipeAction
}

Related

Why is the leading swipe action also duplicated as a trailing action?

I have implemented a leading swipe action ('Delete') on my tableView which for a reason I can't figure out is also appearing as a trailing swipe action. See code below:
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) ->
UISwipeActionsConfiguration? {
let delete1 = deleteAction(at: indexPath)
return UISwipeActionsConfiguration(actions: [delete1])
}
func deleteAction(at indexPath: IndexPath) -> UIContextualAction {
let action = UIContextualAction(style: .destructive, title: "Delete") { (action, view, completion) in
self.delete(at: indexPath)
}
return action
}
I used to have a trailing swipe action, but I deleted this function out completely. When I change 'leadingSwipeActionsConfigurationForRowAt' to 'trailingSwipeActions...' then only the trailing swipe action appears. Be grateful if anyone could tell me what I've missed. Thanks.
Use this code to prevent trailingSwipeAction()
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle
{
return .none
}
or
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return UISwipeActionsConfiguration(actions: [])
}
Because that is the default behaviour, when swipes are enabled. You can do something like this to disable swipes on the trailing side, if you want to implement the destructive delete action on the left only.
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return UISwipeActionsConfiguration(actions: [])
}
By passing an empty set of actions, the trailing swipe will disappear due to having 0 set of possible actions.

How to fix 'black background after deletion of one row"

If a row is deleted, tableView shows black area below cells, while tableView has white background color as with the cell view.
Look at this:
https://www.dropbox.com/s/55ssb73t0ngr9yj/screenshot.png?dl=0
After deleting a row (it can be any one of them, not necessarily the last one), suddenly, black area shows up, though I didn't change any constraint or height of the tableView. Also, behind tableView, there is nothing in this area other than the 'self.view' whose background is also white, and in front of table view, no view is positioned. (one view is there, but it is the size of the screen, so it cannot be black only for this area.)
extension ApptDetailViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return appt.places.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ApptDetailCell", for: indexPath) as! ApptDetailCell
cell.placeNumLabel.text = "Place \(indexPath.row + 1)"
cell.placeNameLabel.text = appt.places[indexPath.row]
return cell
}
}
extension ApptDetailViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let moveString = appt.places.remove(at: sourceIndexPath.row)
let moveBool = appt.reachedPlaces.remove(at: sourceIndexPath.row)
appt.places.insert(moveString, at: destinationIndexPath.row)
appt.reachedPlaces.insert(moveBool, at: destinationIndexPath.row)
print("appt.places: \(appt.places)")
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// deletion occurred.
appt.places.remove(at: indexPath.row)
appt.reachedPlaces.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .right)
}
}
}
As per our comment discussion —You can debug your UI using the view heirarchy debugger. This helps pinpoint anomalies in your views.
Or try to change the tableview background color.

didSelectRowAt indexPath does not when tapped (but does trigger when cell is swiped in either direction)

This is a weird (but should be simple) one. I am simply trying to tap a custom UITableViewCell and trigger a segue to go to another ViewController. didSelectRowAt indexPath does not trigger when the cell is tapped, but it oddly enough does when the cell is swiped from right to left or left to right.
My didSelectRowAt indexPath:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You selected cell number: \(indexPath.row)!")
self.performSegue(withIdentifier: "mySegue", sender: self)
}
(as suggested here)
My ViewController:
import UIKit
class myViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIPickerViewDelegate {
var myData = NSDictionary()
override func viewDidLoad() {
super.viewDidLoad()
fetchMyData()
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.rowHeight = 100
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func fetchMyData() {
// ... fetches my data
}
////////////////////////////////////////////////
//Table view data source
//set number of sections in table
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
//set number of rows in table
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myData.count
}
//delegate information to cells in table rows
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("running tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell...")
// Dequeue cell
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! myCustomCell
cell.cellAmount!.text = "Hello World"
cell.cellTextField2!.text = "Some info"
cell.cellTextField3!.text = "Some other info"
cell.backgroundCardView.backgroundColor = UIColor.red
cell.backgroundCardView.layer.cornerRadius = 8.0
cell.backgroundCardView.layer.masksToBounds = false
cell.backgroundCardView.layer.shadowColor = UIColor.black.withAlphaComponent(0.9).cgColor
cell.backgroundCardView.layer.shadowOffset = CGSize(width: 0, height: 0)
cell.backgroundCardView.layer.shadowOpacity = 0.9
print("finished tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell...")
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You selected cell number: \(indexPath.row)!")
self.performSegue(withIdentifier: "mySegue", sender: self)
}
// func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
// let delete = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
// // delete item at indexPath
// }
// let share = UITableViewRowAction(style: .normal, title: "Disable") { (action, indexPath) in
// // share item at indexPath
// }
//
// share.backgroundColor = UIColor.blue
//
// return [delete, share]
// }
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
return []
}
// Reload the table data when a change is made
// func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
// self.tableView.reloadData()
// }
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
//Table view data source (end)
////////////////////////////////////////////////
}
I have already tried the following as well:
-didSelectRowAtIndexPath: not being called
How to detect Cell selection in UITableView - Swift
Push segue from UITableViewCell to ViewController in Swift
How to tap cell's buttons in UITableViewCell without actionning the cell's segue
is it possible to segue from a UITableViewCell on a UIView to another view
UITableView didSelectRowAt is not called iOS 10, but works for 9.3.5
The UITableViewCell does have UIView and multiple UITextFields, so I did make sure that User Interaction Enabled is unchecked for the UIView and UITextFields.
EDIT: I have also looked in the debugger navigator and can see that the CPU usage percentage increases when I tap a cell (). Maybe there is a way to step deeper and see why that tap doesn't then cause the didSelectRowAt indexPath to be triggered..?
Does anyone know what could possibly be causing didSelectRowAt indexPath to not be triggered when the cell is tapped?
I faced the same issue and found an answer that was applicable for me here. I had this code for keyboard dismiss in viewWillAppear:
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
After commenting this line tapping started to work! But now I will have to find better way for keyboard dismiss. :) Kindly check your exstensions, probably you used similar solution for keyboard dismiss.

Table View: right to left swipe to delete does not show up - swift 3

I've built a simple toDoList app with Swift 3. Now I want to be able to delete my items from a TableView by swiping from right to left. This code is what I've found. But nothing happens when I swipe to the left.
CODE:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return toDoList.count
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "Cell")
cell.textLabel?.text = toDoList[indexPath.row]
return cell
}
//
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
toDoList.remove(at: indexPath.row)
UserDefaults.standard.set(toDoList, forKey: "toDoList")
tableView.reloadData()
}
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .delete
}
This still does not work. Nothing happens when I swipe to the left. The to do List itself is working. I can add items to the table but I just can't remove them.
Thanks :)
Did you implement tableView:canEditRowAtIndexPath: method?
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
EDIT:
Thanks to #rmaddy for mentioning that the default value of tableView:canEditRowAtIndexPath: is true, implementing it doesn't solve the problem.
I'm not pretty sure of what are you trying to do from your code snippet, so make sure that you are implementing the following methods (UITableViewDelegate):
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
toDoList.remove(at: indexPath.row)
UserDefaults.standard.set(toDoList, forKey: "toDoList")
tableView.reloadData()
}
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .delete
}
You can also keep the implementation of tableView:canEditRowAtIndexPath: method:
Asks the data source to verify that the given row is editable.
So, -for example- if you want to let the first row is not editable, i.e user cannot swipe and delete the first row, you should do somthing like:
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
if indexPath.row == 0 {
return false
}
return true
}
Make sure that the UITableViewDataSource and UITableViewDelegate are connected with the ViewController.

Tableviews, cell editing and dragging

I have a swift app with a tableview where the cells are dynamic. What I want to achieve is that the user can side swipe a cell and it brings up two tiles, one for editing and one for deleting (an example of this would be in the messages app where you side swipe for the delete option)
I have got the two tiles to show by using:
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let editRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: " Edit ", handler:{action, indexpath in
});
moreRowAction.backgroundColor = UIColor.orangeColor()
let deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler:{action, indexpath in
return [editRowAction, deleteRowAction]
}
The first issue I have is how can I programatically close the side swipe when the edit option is selected so that the tiles are hidden and the user can see the textfield in the cell?
Second issue, when a cell is in edit mode I want to be able to move the cell in the tableview: following tutorials I have implemented the below:
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
let sourceRow = sourceIndexPath.row;
let destRow = destinationIndexPath.row;
let object = ArrayList.objectAtIndex(sourceRow)
ArrayList.removeObjectAtIndex(sourceRow)
ArrayList.insertObject(object, atIndex: destRow)
}
and set the following when I want to put cell into moving mode
TableView.setEditing(true, animated: true)
Which sort of does what I want, however when I put it into editing mode I get the delete icon on the left side of the cell (red circle with white dash) which I don't want, ideally I'd like my own icon so user can select and drag cell around but I feel this might be pushing it slightly.
Thanks
To get rid of the remove button you should be able to set the editing style to none (or something else)
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return tableView.editing ? UITableViewCellEditingStyle.None : UITableViewCellEditingStyle.Delete
}
To hide to buttons after a swipe you can either set tableView.editing or reload the cell.
tableView.editing = false
alt
tableView.reloadRowsAtIndexPaths(indexPaths: [NSIndexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
//All the involved delegate methods:
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let editRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: " Edit ", handler:{action, indexpath in
self.tableView.editing = false
})
let deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler:{action, indexpath in
self.tableView.editing = false
})
return [editRowAction, deleteRowAction]
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return tableView.editing ? UITableViewCellEditingStyle.None : UITableViewCellEditingStyle.Delete
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
}