简体   繁体   中英

How do I disable the default Delete swipe action and display my custom swipe action instead?

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)

}

I have solved your issue. I hope that will work for you. In trailingSwipeActions method change action style to normal, you will get "Blah" title.

Remove return nil from your if statement.

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    if currentUserID == nil {
        self.showLoginRequiredMessage()
    }
    let trailingAction = UIContextualAction(style: .normal, title: "Blah") { (action, view, boolval) in
        print ("Custom action event")
        tableView.setEditing(false, animated: true)
    }
    trailingAction.backgroundColor = .gray
    return UISwipeActionsConfiguration(actions: [trailingAction])
}

And, add .setEditing(false, animated: true) in below method

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
        self.myTableView.setEditing(false, animated: true)
        if let authenticationController = self.storyboard?.instantiateViewController(withIdentifier: "authenticationScreen") {
            self.present(UINavigationController(rootViewController: authenticationController), animated: true)
        }
    }))

    ac.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: {(action) in
        self.myTableView.setEditing(false, animated: true)
    }))
    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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM