'UITableViewRowAction vs UISwipeActionsConfiguration
The two APIs seem to get the same result. In which case is it better to use one over the other?
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .destructive,
title: "Delete") { (action, indexPath) in
print("DELETE")
}
return [deleteAction]
}
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let DeleteAction = UIContextualAction(style: .destructive, title: "Delete", handler: { (action, view, success) in
print("Delete")
})
DeleteAction.backgroundColor = .red
return UISwipeActionsConfiguration(actions: [DeleteAction])
}
Solution 1:[1]
It does basically the same, but swipe actions are available since iOS 11 was released and have some new features:
- You are able to set actions for trailing swipe as well as for leading swipe
- You can set image of action
action.image = UIImage(...)
. If there is enough space it shows image as well as title
Also, you should use swipe actions because they are preferred and in the future updates UITableViewRowActions
will be deprecated how UITableView
header comment can tell us:
Use -
tableView:trailingSwipeActionsConfigurationForRowAtIndexPath:
instead of this method, which will be deprecated in a future release.
Solution 2:[2]
Here is the code which is working for me
internal func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
// let delete = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
let contextItem = UIContextualAction(style: .destructive, title: "") { (contextualAction, view, boolValue) in
// delete item at indexPath
//if self.isfilterenabled == true {
// return
//}
if self.isfilterenabled == true {
//entryFilter.filteredEntries[indexPath.row]
self.entryFilter.filteredEntries.remove(at: indexPath.row)
} else {
self.data.remove(at: indexPath.row)
}
self.table.deleteRows(at: [indexPath], with: .fade)
self.save()
}
//let share = UITableViewRowAction(style: .normal, title: "SavePDF") { (action, indexPath) in
// share item at indexPath
let contextItemSave = UIContextualAction(style: .normal, title: "") { (contextualAction, view, boolValue) in
let alert = UIAlertController(title: "Done! ", message: "PDF has been saved " ,preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK ", style: .default, handler: nil)
alert.addAction(okAction)
alert.popoverPresentationController?.sourceView = self.view // so that iPads won't crash
// exclude some activity types from the list (optional)
//activityViewController.excludedActivityTypes = [ UIActivityTypeAirDrop, UIActivityTypePostToFacebook ]
// present the view controller
self.present(alert, animated: true, completion: nil)
// present(alert, animated : true, completion : nil )
}
// share.backgroundColor = UIColor.blue
contextItemSave.image = UIImage(named:"PDF.jpg")
contextItem.image = UIImage(named:"delete.jpg")
let swipeActions = UISwipeActionsConfiguration(actions: [contextItem,contextItemSave])
return swipeActions
//return [delete, share]
}`
Solution 3:[3]
I have created an extension for UISwipeActionsConfiguration
which you can use if you have a sizing issue with your image. Basically, the idea is to create an Attributed String from the image and the text and set it to label and create an image from that label. And append it to UIContextualAction
's image
property.
extension UISwipeActionsConfiguration {
public static func makeTitledImage(
image: UIImage?,
title: String,
textColor: UIColor = .white,
font: UIFont = .systemFont(ofSize: 14),
size: CGSize = .init(width: 50, height: 50)
) -> UIImage? {
/// Create attributed string attachment with image
let attachment = NSTextAttachment()
attachment.image = image
let imageString = NSAttributedString(attachment: attachment)
/// Create attributed string with title
let text = NSAttributedString(
string: "\n\(title)",
attributes: [
.foregroundColor: textColor,
.font: font
]
)
/// Merge two attributed strings
let mergedText = NSMutableAttributedString()
mergedText.append(imageString)
mergedText.append(text)
/// Create label and append that merged attributed string
let label = UILabel(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
label.textAlignment = .center
label.numberOfLines = 2
label.attributedText = mergedText
/// Create image from that label
let renderer = UIGraphicsImageRenderer(bounds: label.bounds)
let image = renderer.image { rendererContext in
label.layer.render(in: rendererContext.cgContext)
}
/// Convert it to UIImage and return
if let cgImage = image.cgImage {
return UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .up)
}
return nil
}
}
And you can use it like this;
public func tableView(
_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
) -> UISwipeActionsConfiguration?
{
let deleteAction = UIContextualAction(
style: .normal,
title: nil,
handler: { [weak self] (_, _, success: (Bool) -> Void) in
success(true)
print("Your action in here")
}
)
deleteAction.image = UISwipeActionsConfiguration.makeTitledImage(
image: UIImage(named: "delete_icon"),
title: "Delete")
)
deleteAction.backgroundColor = .orange
return UISwipeActionsConfiguration(actions: [deleteAction])
}
Solution 4:[4]
the method (editActionsForRowAt) is deprecated
The modern approach uses different method which is trailingSwipeActionsConfigurationForRowAt indexPath to provide actions for row when user swipes to the left.
There is also leadingSwipeActionsConfigurationForRowAt indexPath to provide actions when user swipes to the right.
here is example
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let deleteAction = UIContextualAction(style: .destructive, title: nil) { (_, _, completionHandler) in // delete the item here completionHandler(true) }
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Zouhair Sassi |
Solution 2 | Guri S |
Solution 3 | ysnzlcn |
Solution 4 | Saad |