trailingSwipeActionsConfigurationForRowAt not work in stability - ios

I am trying to make swipe-able table view cell for iOS 11 and above and trying to use the trailingSwipeActionsConfigurationForRowAt but it works on iPad and doesn't work on iPhone. It is not called in iPhone.
Surprisingly if I try to swipe the cell more then 10 or 20 times it sometimes works for once.
Here is my controller's table view extension
import UIKit
extension CustomViewController: UITableViewDelegate, UITableViewDataSource {
func initTableView() {
tableView.register(cell: SingleLineListItemViewCell.self)
tableView.delegate = self
tableView.dataSource = self
tableView.estimatedRowHeight = 64
tableView.rowHeight = UITableView.automaticDimension
tableView.backgroundColor = .green
tableView.isEditing = false
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let model = SingleLineListItemViewModel(title: "coko")
let cell = tableView.dequeueReusableCell(withIdentifier: SingleLineListItemViewCell.reuseIdentifier) as? SingleLineListItemViewCell
cell?.model = model
cell?.isFirst = indexPath.row == 0
cell?.isLast = indexPath.row == 2
return cell!
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return nil
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 0
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 64.0
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
print("didSelectRowAt....")
router?.routeToTransfer()
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
#available(iOS 11.0, *)
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return nil
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
// Action here
// In case of delete, you can simply do:
if editingStyle == .delete {
//Remove item at relative position from datasource array
//Reload tableview at the respective indexpath
}
}
#available(iOS 11.0, *)
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { _, _, _ in
//YOUR_CODE_HERE
}
deleteAction.backgroundColor = .red
let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
configuration.performsFirstActionWithFullSwipe = false
return configuration
}
}
Any help would be much appreciated.

The only obvious thing wrong with this is that you're not calling the completion handler. According to the API documentation it is necessary to call the completion handler to indicate whether the operation was successful. What it actually does I have no idea...
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { _, _, completionHandler in
//YOUR_CODE_HERE
completionHandler(true)
}
deleteAction.backgroundColor = .red
let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
configuration.performsFirstActionWithFullSwipe = false
return configuration
}
If this doesn't make any difference, do you have any other gesture recognisers that could be conflicting with the swipe action?

you can try this one
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "Delete"
}
// this method handles row deletion
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// remove the item from the data model
// delete the table view row
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Not used in our example, but if you were adding a new row, this is where you would do it.
}
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let action = UIContextualAction(
style: .normal,
title: "Delete",
handler: { (action, view, completion) in
//do what you want here
completion(true)
})
action.backgroundColor = .red
let configuration = UISwipeActionsConfiguration(actions: [action])
configuration.performsFirstActionWithFullSwipe = false
return configuration
}

Here is are actions defined as well (point 1 and 2);
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "") { _, _, completionHandler in
// 1. remove object from your array
scannedItems.remove(at: indexPath.row)
// 2. reload the table, otherwise you get an index out of bounds crash
self.tableView.reloadData()
completionHandler(true)
}
deleteAction.backgroundColor = .systemOrange
deleteAction.image = UIImage(named: "trash")
let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
configuration.performsFirstActionWithFullSwipe = true
return configuration
}

Related

Applying NSDiffableDataSourceSnapshot to UITableViewDiffableDataSource cause 'NSInternalInconsistencyException'

I am trying to implement a UITableViewViewDiffableDataSource for my tableview. My code compiles fine, however I keep running into this error the first time I apply a snapshot to it, with the following error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: section < [_state.dataSourceSnapshot numberOfSections]'
Here is my code:
BaseDisplayManager
class BaseDisplayManager: NSObject, UITableViewDelegate, BaseDiffableDataSourceDelegate {
var tableData = [[BaseViewModelProtocol]]()
var sections: [DiffableSection] = []
...
func setupDiffableDataSource(forTableView tableView: UITableView) {
dataSource = BaseDiffableDataSource(tableView: tableView, cellProvider: { (tableView, indexPath, model) -> UITableViewCell? in
guard let model = model as? BaseViewModelProtocol else { return nil }
let cell = tableView.dequeueReusableCell(withIdentifier: model.cellIdentifier, for: indexPath)
(cell as? TableViewCell)?.model = model
(cell as? NoSwipeTableViewCell)?.model = model
return cell
})
dataSource.delegate = self
}
func reloadSnapshot() {
var snapshot = NSDiffableDataSourceSnapshot<AnyHashable, AnyHashable>()
snapshot.appendSections(sections.map { $0.sectionIdentifier() })
sections.forEach { [weak self] section in
guard let items = self?.tableData[section.sectionIndex()] as? [AnyHashable] else { return }
snapshot.appendItems(items, toSection: section.sectionIdentifier())
}
dataSource.apply(snapshot, animatingDifferences: true)
}
DiffableSection
protocol DiffableSection {
func sectionIndex() -> Int
func sectionIdentifier() -> AnyHashable
}
BaseDiffableDataSource
protocol BaseDiffableDataSourceDelegate: class {
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)
}
class BaseDiffableDataSource: UITableViewDiffableDataSource<AnyHashable, AnyHashable> {
weak var delegate: BaseDiffableDataSourceDelegate! = nil
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return delegate.tableView(tableView, canEditRowAt: indexPath)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
return delegate.tableView(tableView, commit: editingStyle, forRowAt: indexPath)
}
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return delegate.tableView(tableView, canMoveRowAt: indexPath)
}
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
return delegate.tableView(tableView, moveRowAt: sourceIndexPath, to: destinationIndexPath)
}
}
}
I ran into the same issue in a ViewController which was a subclass of UITableViewController.
For me it was that I was configuring my datasource and applying a snapshot in viewWillAppear() AND calling super.viewWillAppear() before. Removing the super call did the trick.

UITableView not showing Delete button on clicking minus button(Only on iOS 13)

I have a table view to shows a list of items. I have implemented the default editing style delete. It's been working till iOS 12. But not on iOS 13. It does not show the Delete button when clicking the minus button.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return machineOrders.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MachineOrderCell") as! MachineOrderCell
let machineOrder = machineOrders[indexPath.row]
cell.update(with: machineOrder)
cell.decreaseQuantityButton.isEnabled = canDecreaseQuantity(for: machineOrder)
cell.onDecreaseQuantity = {
self.delegate.view(self, didSelectDecreaseQuantity: machineOrder)
}
cell.onIncreaseQuantity = {
self.delegate.view(self, didSelectIncreaseQuantity: machineOrder)
}
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {
navigationItem.rightBarButtonItem = doneBarButton
}
func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) {
navigationItem.rightBarButtonItem = !isCartEmpty ? (tableView.isEditing ? doneBarButton : editBarButton) : nil
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
let machineOrder = machineOrders[indexPath.row]
if editingStyle == .delete {
self.delegate.view(self, didSelectDelete: machineOrder)
}
}
Press minus button for some seconds, I mean long press, then it will work.

EditActionsForRowAt not working for two tableView on Scrollview in Swift 3

I use two tableView with 5 and 3 cells over scrollview . Trying to use swipeable gesture on both tableView using editActionsForRowAt method of tableView But it just swipe only three cells of first tableView and other cell swipe by trying 5 to 7 times or unswipeable. Help me to get it ,
Thanks in advance
my code
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == table1{
return 5
}
else if tableView == table2{
return 3
}
else{
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == table1{
let cell = meetingTable.dequeueReusableCell(withIdentifier: "myCell") as! meetingCell
cell.cell_name.text = "abc"
cell.cell_copny.text = "08276"
return cell
}
else{
let cell = followTable.dequeueReusableCell(withIdentifier: "myCell") as! FollowUpCell
cell.cell_name.text = "abc"
cell.cell_phone.text = "134135"
return cell
}
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let Btn1 = UITableViewRowAction(style: .normal, title: "\u{1F4DE}\n Btn1") { action, index in
//code
}
Btn1.backgroundColor = UIColor.lightGray
let Btn2 = UITableViewRowAction(style: .normal, title: "\u{1F4D3}\n Btn2") { action, index in
//code
}
Btn2.backgroundColor = UIColor.orange
return [Btn2,Btn1]
}

Swap items in UITableView - has UI issues

I am trying to implement a swap feature inside the uitableview, Currently my table looks like this..
Then i implemented these method
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.none
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
swap(&groupList[sourceIndexPath.row], &groupList[destinationIndexPath.row])
reloadData()
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
// delete item at indexPath
print("Delete at index : \(indexPath.row)")
}
delete.backgroundColor = UIColor(red: 210.0/255, green: 30.0/255, blue: 75.0/255, alpha: 1.0)
return [delete]
}
Now it looks like this..
I see two white borders left and right, i want to change that background color of those borders..
also slide to delete is not working anymore (unable to slide right to left, as shown in first image)
can someone help me to fix this
Change cell editing style none to delete
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.delete
}
Use below code. this will work.
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "identuty", for: indexPath)
return cell
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
// delete item at indexPath
print("Delete at index : \(indexPath.row)")
}
delete.backgroundColor = UIColor(red: 210.0/255, green: 30.0/255, blue: 75.0/255, alpha: 1.0)
return [delete]
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.delete
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}

Change the text of the cell delete button

i'm trying to change the delete button of a cell.
I have 2 functions :
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let titleBtn = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Supprimer") { (action , indexPath ) -> Void in
self.isEditing = false
//ackAction.backgroundColor = UIColor.orange
}
return [titleBtn]
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
But, when I run my app, the text of the button is changed but the delete doesn't work (i can't delete data from my array and the row of my tableview). Before to add this functions all worked perfectly.
A detail: in the canEditRowAt function, I tried to return false too...
Thanks by advance
if you want to change the text of the delete button, conform this method in the UITableViewDelegate:
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String?
{
return "Your new title"
}
To delete the item from the array conform this method
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
if (editingStyle == UITableViewCellEditingStyle.delete)
{
yourDataSourceArray.remove(at: indexPath.row)
yourTableView.reloadData()
}
}
You can either use default delete action and change its title like this.
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String?
{
return "MyAction"
}
or you can create your own action buttons like this.
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .default, title: "Delete") {action in
//handle delete
}
let editAction = UITableViewRowAction(style: .normal, title: "Edit") {action in
//handle edit
}
return [deleteAction, editAction]
}

Resources