I am making a CheckList application with a UITableView. I was wondering how to add a swipe to delete a UITableViewCell.
This is my ViewCont
@available(iOS 11.0, *)
    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let editAction = UIContextualAction.init(style: UIContextualAction.Style.normal, title: "Edit", handler: { (action, view, completion) in
            //TODO: Edit
            completion(true)
            self.popUpViewPresent(index:indexPath.row)
        })
        let deleteAction = UIContextualAction.init(style: UIContextualAction.Style.destructive, title: "Delete", handler: { (action, view, completion) in
            //TODO: Delete
            completion(true)
            self.deleteTagAction(senderTag:indexPath.row)
        })
        editAction.image = UIImage(named: "Edit-white")
        deleteAction.image = UIImage(named: "Delete-white")
        editAction.backgroundColor = UIColor.gray
        deleteAction.backgroundColor = UIColor.red
        let config = UISwipeActionsConfiguration(actions: [deleteAction, editAction])
        config.performsFirstActionWithFullSwipe = false
        return config
    }
Swift 4 -- @available(iOS 11.0, *)
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let edit = UIContextualAction(style: .normal, title: "") { (action, view, nil) in
        let refreshAlert = UIAlertController(title: "Deletion", message: "Are you sure you want to remove this item from cart? ", preferredStyle: .alert)
        refreshAlert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (action: UIAlertAction!) in
        }))
        refreshAlert.addAction(UIAlertAction(title: "No", style: .default, handler: { (action: UIAlertAction!) in
            refreshAlert .dismiss(animated: true, completion: nil)
        }))
        self.present(refreshAlert, animated: true, completion: nil)
    }
    edit.backgroundColor = #colorLiteral(red: 0.3215686275, green: 0.5960784314, blue: 0.2470588235, alpha: 1)
    edit.image = #imageLiteral(resourceName: "storyDelete")
    let config = UISwipeActionsConfiguration(actions: [edit])
    config.performsFirstActionWithFullSwipe = false
    return config
}
Works for me in Swift 2.0
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
}
override func tableView(tableView: UITableView,
    editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
    let block = UITableViewRowAction(style: .Normal, title: "Block") { action, index in
        print("Block")
        self.removeObjectAtIndexPath(indexPath, animated: true)
    }
    let delete = UITableViewRowAction(style: .Default, title: "Delete") { action, index in
        print("Delete")
        self.removeObjectAtIndexPath(indexPath, animated: true)
    }
    return [delete, block]
}
Swift 4
@available(iOS 11.0, *)    
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
            let action =  UIContextualAction(style: .normal, title: "", handler: { (action,view,completionHandler ) in
                //do stuff
                completionHandler(true)
                let data:NSDictionary = self.conversations[indexPath.row] as! NSDictionary
                print(data)
                let alert:UIAlertController = UIAlertController(title: "", message: "are you sure want to delete ?", preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "CANCEL", style: UIAlertActionStyle.cancel, handler: { (action) in
                }))
                self.present(alert, animated: true, completion: nil)
            })
            action.image = UIImage(named: "")
            action.backgroundColor = UIColor(red: 0/255, green: 148/255, blue: 204/255, alpha: 1.0)
            let confrigation = UISwipeActionsConfiguration(actions: [action])
            return confrigation
        }
swift 3
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if (editingStyle == UITableViewCellEditingStyle.delete) {
        arrayCityName.remove(at: indexPath.row)
        self.tableCityName.reloadData()
    }
}
For > ios 13 https://gist.github.com/andreconghau/de574bdbb468e001c404a7270017bef5#file-swipe_to_action_ios13-swift
/*
     SWIPE to Action
     */
    
    func tableView(_ tableView: UITableView,
                   editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
        return .none
    }
    // Right Swipe
    func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        
        let action = UIContextualAction(style: .normal,
                                        title: "Favourite") { [weak self] (action, view, completionHandler) in
                                            self?.handleMarkAsFavourite()
                                            completionHandler(true)
        }
        action.backgroundColor = .systemBlue
        
        return UISwipeActionsConfiguration(actions: [action])
    }
    
    func tableView(_ tableView: UITableView,
                       trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        // Archive action
        let archive = UIContextualAction(style: .normal,
                                         title: "Archive") { [weak self] (action, view, completionHandler) in
                                            self?.handleMoveToArchive()
                                            completionHandler(true)
        }
        archive.backgroundColor = .systemGreen
        // Trash action
        let trash = UIContextualAction(style: .destructive,
                                       title: "Trash") { [weak self] (action, view, completionHandler) in
            self?.handleMoveToTrash(book: (self?.books![indexPath.row]) as! BookItem)
                                        completionHandler(true)
        }
        trash.backgroundColor = .systemRed
        // Unread action
        let unread = UIContextualAction(style: .normal,
                                       title: "Mark as Unread") { [weak self] (action, view, completionHandler) in
                                        self?.handleMarkAsUnread()
                                        completionHandler(true)
        }
        unread.backgroundColor = .systemOrange
        let configuration = UISwipeActionsConfiguration(actions: [trash, archive, unread])
        // If you do not want an action to run with a full swipe
        configuration.performsFirstActionWithFullSwipe = false
        return configuration
    }
    
    
    
    private func handleMarkAsFavourite() {
        print("Marked as favourite")
    }
    private func handleMarkAsUnread() {
        print("Marked as unread")
    }
    private func handleMoveToTrash(book: BookItem) {
        print("Moved to trash")
        print(book)
        let alert = UIAlertController(title: "Hi!", message: "Bạn có muốn xóa \(book.name)", preferredStyle: .alert)
            
             let ok = UIAlertAction(title: "Xóa", style: .default, handler: { action in
                book.delete()
                self.listBook.reloadData()
             })
             alert.addAction(ok)
             let cancel = UIAlertAction(title: "Hủy", style: .default, handler: { action in
             })
             alert.addAction(cancel)
             DispatchQueue.main.async(execute: {
                self.present(alert, animated: true)
        })
        
    }
    private func handleMoveToArchive() {
        print("Moved to archive")
    }