swiftuibarbuttonitemrightbarbuttonitem

Change barButtonSystemItem after tapping


I have a bar button in the right side of the screen, it's barButtonSystemItem: .edit and it's used to put tableView in the editing mode. I want when, user tap on it, it change to barButtonSystemItem: .done and it close tableview from editing mode. Just to be clear, every time that barButton is clicked, the type of it should be change from edit to done.

Here is my code, but it always stay with edit, and not changing to done

fileprivate func addBarButton() {
    if tableView.isEditing {
        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(editButtonAction))
    } else {
        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(doneButtonAction))
    }
}


@objc func editButtonAction(sender: UIBarButtonItem) {
    tableView.isEditing = !tableView.isEditing
}



@objc func doneButtonAction(sender: UIBarButtonItem) {
    tableView.isEditing = !tableView.isEditing
}

override func viewDidLoad() {
    super.viewDidLoad()
    addBarButton()
    tableView?.isEditing = true
}

Solution

  • In the bodies of methods editButtonAction and editButtonAction you only change the tableView editing state by doing tableView.isEditing = !tableView.isEditing. This action does nothing to navigationItem at all.

    I'd recommend you to refactor the code a bit by renaming addBarButton into updateBarButton and call it every time when the table editing state changes and additionally from viewDidLoad as you do now. So your code would become something like this:

      fileprivate func updateBarButton() {
        if tableView.isEditing {
            navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(editButtonAction))
        } else {
            navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(doneButtonAction))
        }
    }
    
    
    @objc func editButtonAction(sender: UIBarButtonItem) {
        tableView.isEditing = !tableView.isEditing
        updateBarButton() // Note the additional call of the update method
    }
    
    @objc func doneButtonAction(sender: UIBarButtonItem) {
        tableView.isEditing = !tableView.isEditing
        updateBarButton() // Note the additional call of the update method
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView?.isEditing = true
        updateBarButton() // Note that we call this method after changing the table view state so that it will have the most recent value
    }