UITableViewRowAction vs UISwipeActionsConfiguration
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.
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]
}`
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])
}