editActionsForRowAtIndexPath not called, both commit editingStyle and canEditRowAt present - swift

I am trying to add a second swipe button to my table view rows, but editActionsForRowAtIndexPath is not being called when I swipe a row. This is despite my class declaring both
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
and
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
}
Both of these are called when I swipe because I also have a regular delete button.
My editActionsForRowAtIndexPath function is written as follows:
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewRowAction? {
print("triggered!")
let more = UITableViewRowAction(style: .default, title: "More") { action, index in
print("more button tapped")
}
more.backgroundColor = UIColor.blue
return more
}
Thanks in advance!

You are not using the updated Swift 3 API for this particular method. The delegate method should be written as:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
print("triggered!")
let more = UITableViewRowAction(style: .default, title: "More") { action, index in
print("more button tapped")
}
more.backgroundColor = UIColor.blue
return [more]
}

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 do I move custom cells to left in editing mode in UITableView

I have custom cells of UITableView which consist of UIImage and textLabel. When I select the editing mod, the textLabel shows the following image;
I want to move it to left. I tried all of things to do but it didn't work.
Please let me know.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allRows.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "editCell", for: indexPath) as! CustomTableView
cell.textLabel?.text = self.allRows[indexPath.row].bname
cell.textLabel?.textAlignment = .left
let image:UIImage = UIImage(named: "group")!
cell.imageView!.image = image
return cell
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle{
return .delete
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
if editingStyle == .delete{
self.allRows.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath as IndexPath], with: .fade)
}
}
#objc func leftEditButtonPressed(_ sender: UIButton) {
self.tableView!.isEditing = true
self.tableView?.setEditing(true, animated: true)
}
look at this, I hope it helps you:
swipe left/right in tableViewCell
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let closeAction = UIContextualAction(style: .normal, title: "Close", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
print("OK, marked as Closed")
success(true)
})
closeAction.image = UIImage(named: "tick")
closeAction.backgroundColor = .purple
return UISwipeActionsConfiguration(actions: [closeAction])
}
Try using the following code:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataArr.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80.0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableCell") as? TestTableCell else {
return UITableViewCell()
}
cell.customImageView.image = #imageLiteral(resourceName: "ic_audio")
cell.customTitleLabel.text = self.dataArr[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.delete
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("delete at \(indexPath.row)")
}
}
Here is the output for this code:
Note: You can change the editing action in editingStyleForRowAt method and for performing the action you need to write the logic in commit editingStyle method.
Hope this help you!
I suggest you to create new label in that UITableViewCell and connect that label to custom UITableViewCell class ! then you are free to do anything !
Swift 4 :
Create a new class which is subclass of UITableViewCell !
In your storyboard in right menu which called Utilities in toolbar of Utilities go to the Identity inspector defince your cell class to your new UITableViewCell class
Drag and drop UILabel from Object library into your cell
now using drag and drop connect that label to your UITableViewCell class then create an Outlet
Perfect !
now use myLabel instead of textLabel ;)
dont forget to cast your cell as! YourCustomCellClass
Good Luck ;)

How to edit row of cell?

I can not turn on editing mode in the first row of the cell. I tried this code but it didn't help.
public func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
if indexPath.row == 1{
return true
}
return false
}
Can someone help me?
Firstly, make sure your have added UITableViewDataSource protocol. Secondly, you may also need the following implementations.
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let myAction = UITableViewRowAction(style: .normal, title: "MY_ACTION") { (action, indexPath) in
print("I'm here")
}
return [myAction]
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
}
If you want to edit first row then replace
if indexPath.row == 1
with
if indexPath.row == 0
Because indexPath.row starts from 0 not from 1.
Hope that will help.
EDIT:
Since you didn't show your complete code I am adding example code here.
check below code:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tbl: UITableView!
let arr = ["1", "2", "3"]
override func viewDidLoad() {
super.viewDidLoad()
tbl.dataSource = self
tbl.delegate = self
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tbl.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = self.arr[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
//set 0 for first cell
if indexPath.row == 0 {
return true
}
return false
}
//Need this method for delete cell
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
tbl.reloadData()
}
}
}

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.

UITableViewRowAction not working

I have an UITableView that I manage in a controller with UITableViewDelegate and UITableViewDataSource. In this table I have a custom cell, the problem is that the function editActionsForRowAtIndexPath gets called only sometimes (maybe when I swype in a particular way, I don't know), my code is the following:
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let doneAction: UITableViewRowAction
//let highlightAction: UITableViewRowAction
if(self.compiti[indexPath.row].completato){
doneAction = UITableViewRowAction(style: .Normal, title: "Da Fare") { (UITableViewRowAction, indexPath: NSIndexPath!) -> Void in
let compito = self.compiti[indexPath.row]
self.db.contrassegnaCompito(compito)
UITableViewRowAction
}
doneAction.backgroundColor = UIColor.redColor()
}else{
doneAction = UITableViewRowAction(style: .Normal, title: "Fatto") { (UITableViewRowAction, indexPath: NSIndexPath!) -> Void in
let compito = self.compiti[indexPath.row]
self.db.contrassegnaCompito(compito)
}
doneAction.backgroundColor = UIColor(red: 67/255, green: 160/255, blue: 71/255, alpha: 0.7)
}
return [doneAction]
}
you need to add this method implementation as well or you won't be able to swipe to display the actions
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
// it can be empty
}
It works for me with this code, try starting from this and you will probably find when the problem occurs
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
var doneAction :UITableViewRowAction!
doneAction = UITableViewRowAction(style: .Default, title: "Da Fare") { (UITableViewRowAction, indexPath: NSIndexPath!) -> Void in
UITableViewRowAction
}
return [doneAction]
}