UITableViewRowAction not working - swift

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]
}

Related

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 ;)

Change editingStyle background color and label for cells in tableView

I have a tableview where I'm trying to implement a swipe-to-delete action.
I'm using swift 4 and Xcode 9.
So far I have the next code which allows me to show a delete label when swipe:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
print("deleting row")
default:
return
}
}
So far so good, now I'd like to change the background red color to another one and if it's also possible i'd like to show an icon instead of a label.
I'm trying this code I've seen for Swift 4 but it's complaining when creating the button:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteButton = UITableViewRowAction(style: .default, title: "Delete") { (action, indexPath) in
self.tableView.dataSource?.tableView!(self.tableView, commit: .delete, forRowAt: indexPath)
return
}
deleteButton.backgroundColor = UIColor.black
return [deleteButton]
}
It gives this error -> Ambiguous reference to member 'tableView(_:numberOfRowsInSection:)'
I don't know if I'm trying the good way to edit, or if it's not editable at all on swift 4.
Any help is appreciated,
Thanks!
I am using Xcode 9.2 and swift 4. Used same code but with no errors. Full code is here. That may help to you.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height), style: .plain)
tableView.dataSource = self
tableView.delegate = self
self.view.addSubview(tableView)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell.textLabel?.text = "Lalala"
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
print("deleting row")
default:
return
}
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteButton = UITableViewRowAction(style: .default, title: "Delete") { (action, indexPath) in
self.tableView.dataSource?.tableView!(self.tableView, commit: .delete, forRowAt: indexPath)
return
}
deleteButton.backgroundColor = UIColor.black
return [deleteButton]
}
}
I was tried like this ,may be this will help you.
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .default, title: "Delete") { (action, indexPath) in
print("Did tap the button")
self.deleteSession(sessionId: self.tableModel[indexPath.row].Id)
print("the session id is '\(self.tableModel[indexPath.row].Id)'")
self.tableModel.remove(at: indexPath.row)
print("\(indexPath.row)")
tableView.deleteRows(at: [indexPath], with: .fade)
print("\([indexPath])")
self.medilogTableView.reloadData()
}
deleteAction.backgroundColor = UIColor.red
//deleteAction.backgroundColor = UIColor(patternImage: UIImage(named: "delete_button")!)
//renameAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0)
return [deleteAction]
}
medilogTableView is name of the table
You must implement your edit code inside the "in" callback :
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteButton = UITableViewRowAction(style: .default, title: "Delete") { (action, indexPath) in
// here implement your delete code
}
deleteButton.backgroundColor = .blue
return [deleteButton]
}
Sample of implementation for your "delete code" :
self.tableView.beginUpdates()
self.data.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .left)
self.tableView.endUpdates()

editActionsForRowAtIndexPath not called, both commit editingStyle and canEditRowAt present

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]
}

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) {
}

Delete Button Not Appearing in UITableViewCell

In my program, I am trying to implement the swipe to delete feature on UITableViewCells but the delete button is not appearing even though the cell does move as it should when swiping. Does anyone know why?
Here is my code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var cell = tableView.cellForRowAtIndexPath(indexPath) as resultsCell
otherName = cell.usernameLbl.text!
otherProfileName = cell.profileNameLbl.text!
self.performSegueWithIdentifier("goToConversationVC", sender: self)
}
override func viewWillAppear(animated: Bool) {
self.navigationItem.hidesBackButton = true
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return resultsUsernameArray.count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 120
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:resultsCell = tableView.dequeueReusableCellWithIdentifier("Cell") as resultsCell
cell.usernameLbl.text = self.resultsUsernameArray[indexPath.row]
cell.profileNameLbl.text = self.resultsProfileNameArray[indexPath.row]
resultsImageFiles[indexPath.row].getDataInBackgroundWithBlock {
(imageData: NSData!, error:NSError!) -> Void in
if error == nil {
let image = UIImage(data: imageData)
cell.profileImg.image = image
}
}
return cell
}
#IBAction func logoutBtn_click(sender: AnyObject) {
PFUser.logOut()
self.navigationController?.popToRootViewControllerAnimated(true)
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
// called when a row is moved
func tableView(tableView: UITableView,
moveRowAtIndexPath sourceIndexPath: NSIndexPath,
toIndexPath destinationIndexPath: NSIndexPath) {
// remove the dragged row's model
let val = friends.removeAtIndex(sourceIndexPath.row)
// insert it into the new position
friends.insert(val, atIndex: destinationIndexPath.row)
}
func tableView(tableView: UITableView,
commitEditingStyle editingStyle: UITableViewCellEditingStyle,
forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle {
case .Delete:
// remove the deleted item from the model
friends.removeAtIndex(indexPath.row)
// remove the deleted item from the `UITableView`
resultsTable.editing = resultsTable.editing
resultsTable.editing = true
self.resultsTable.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
default:
return
}
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return .Delete
}
Your UITableView is too big hence the delete button is out of the screen