Reputation: 524
I am following a tutorial online regarding a TableView Cell swipe action.
I can explain to myself every line, except completionHandler(true)
This is the code snippet
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { (action, sourceView, completionHandler) in
//Delete
self.restaurantNames.remove(at: indexPath.row)
self.restaurantLocations.remove(at: indexPath.row)
self.restaurantTypes.remove(at: indexPath.row)
self.restaurantIsVisited.remove(at: indexPath.row)
self.restaurantImages.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .fade)
// Call completion handler to dismiss the action button
completionHandler(true)
}
let shareAction = UIContextualAction(style: .normal, title: "Share") { (action, sourceView, completionHandler) in
let defaultText = "Just checking in at" + self.restaurantNames[indexPath.row]
let activityController = UIActivityViewController(activityItems: [defaultText], applicationActivities: nil)
self.present(activityController, animated: true, completion: nil)
// Call completion handler to dismiss the action button
completionHandler(true)
}
let swipeConfiguration = UISwipeActionsConfiguration(actions: [deleteAction, shareAction])
return swipeConfiguration
}
I don't quite understand what does this mean? Thanks in advance
Upvotes: 6
Views: 2304
Reputation: 9503
Explanation: You call the completion handler with true to indicate you performed the action or false if you could not for some reason.
Check below demo code work:
func contextualToggleFlagAction(forRowAtIndexPath indexPath: IndexPath) -> UIContextualAction {
var email = data[indexPath.row]
let action = UIContextualAction(style: .normal,
title: "Flag") { (contextAction: UIContextualAction, sourceView: UIView, completionHandler: (Bool) -> Void) in
if email.toggleFlaggedFlag() {
self.data[indexPath.row] = email
self.tableView.reloadRows(at: [indexPath], with: .none)
completionHandler(true) // your task is successfully done.
} else {
completionHandler(false) // With some reason you unable to perform task so now you returning false.
}
}
action.image = UIImage(named: "flag")
action.backgroundColor = email.isFlagged ? UIColor.gray : UIColor.orange
return action
}
Upvotes: 3
Reputation: 546
All of the existing answers just paste Apple's documentation which answers precisely nothing. It says when it should be called but nothing about what it does to the UI.
As far as I can tell, calling completionHandler with either value will collapse the buttons. You can see this in action by calling the completion handler in a dispatch_after
block with a delay. Specifying true vs. false makes no difference in my tests.
I have a feeling that I'm missing something, but Apple's documentation is opaque here.
Upvotes: 11
Reputation: 285039
Actually the comment before the completionHandler
line explains the purpose. The completion handler is a closure which must be called at the end of the action to dismiss the action and to pass a status value.
More information from the documentation
completionHandler
The handler block for you to execute after you have performed the action. This block has no return value and takes the following parameter:
actionPerformed
A Boolean value indicating whether you performed the action. Specify
true
if you performed the action orfalse
if you were unable to perform the action for some reason.
Upvotes: 1
Reputation: 4099
Third parameter of the UIContextualAction
handler is a closure that tells UIContextualAction
whether or not you performed the action. By calling completionHanlder(true)
you're notifying UIContextualAction
that you performed the requested action. If, for example, there was an error in your handler that precluded you from performing the desired action, you can notify the handler by calling completionHandler(false)
.
Documentation: https://developer.apple.com/documentation/uikit/uicontextualaction/handler
Upvotes: 2