I'm implementing leading/trailing swipe actions in my app.
The leading swipe action is to join/leave an event in the table. The trailing swipe action is to delete an event. Both of these swipe actions should be conditional, based primarily on if the user is logged in or not.
If the user swipes left or right, and the user is not logged in, I want to display an alert ("Login required...").
If the user is logged in, the leading action will conditionally be titled "Leave" or "Join" depending on if the user has already joined the event or not. The trailing "Delete" action will be created only if the user is the also the creator of the event.
When I test the app and the user is logged in, everything works perfectly. (That was working before I decided to add the conditional element.)
When I test the app, and the user is not logged in, the leading swipe works perfectly: I swipe left (in my case), the alert pops up. No swipe action appears in the TableViewCell.
The trailing swipe also shows the alert and reacts correctly, but for some reason it's also showing a "Delete" action, even though my code uses the title "Blah". After dismissing the alert, the red "Delete" action is still visible and clickable.
I've also completely removed the "trailingSwipe..." method but the "Delete" action still appears, so I need to figure out where the default is so I can turn it off and/or override it.
How do I prevent the default Delete action from appearing and display my action instead?
Here's my code for the leading swipe:
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
if currentUserID == nil {
showLoginRequiredMessage()
return nil
} else {
var userName = people.randomElement() // for testing
if event.eventMembers.contains(userName) {
let index = event.eventMembers.firstIndex(of: userName)!
let leaveAction = UIContextualAction(style: .normal, title: "Leave") { (action, view, nil) in
event.eventMembers.remove(at: index)
tableView.setEditing(false, animated: true)
tableView.reloadRows(at: [indexPath], with: .automatic)
self.saveEvents()
}
leaveAction.backgroundColor = .red
return UISwipeActionsConfiguration(actions: [leaveAction])
} else {
let joinAction = UIContextualAction(style: .normal, title: "Join") { (action, view, nil) in
event.eventMembers.append(userName)
tableView.setEditing(false, animated: true)
tableView.reloadRows(at: [indexPath], with: .automatic)
self.saveEvents()
}
joinAction.backgroundColor = .green
return UISwipeActionsConfiguration(actions: [joinAction])
}
}
}
Here's my code for the trailing swipe:
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
if currentUserID == nil {
showLoginRequiredMessage()
return nil
} else {
let trailingAction = UIContextualAction(style: .destructive, title: "Blah") { (action, view, nil) in
tableView.setEditing(false, animated: true)
print ("Delete this event")
}
trailingAction.backgroundColor = .red
return UISwipeActionsConfiguration(actions: [trailingAction])
}
}
And here's the code for the alert:
private func showLoginRequiredMessage() {
let ac = UIAlertController(title: "Login Required", message: "To modify an event, you must first login", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Sign In", style: .default, handler: {(action) in
if let authenticationController = self.storyboard?.instantiateViewController(withIdentifier: "authenticationScreen") {
self.present(UINavigationController(rootViewController: authenticationController), animated: true)
}
}))
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(ac, animated: true)
}
Based on ChillY's answer to this question (Why is the leading swipe action also duplicated as a trailing action?), I realized the problem was that I was returning nil
instead of UISwipeActionsConfiguration(actions: [])
.
Now I just have to figure out why the swipes are not disappearing after the action has been executed. Any ideas?