skip to Main Content

Here is the bar button behavior found in the system language settings:

enter image description here

  1. When the Edit bar button is pressed, the Back bar button will be replaced by the Cancel bar button.
  2. When the Done bar button is pressed, the Cancel bar button will be replaced by the Back bar button.

I am using UIViewController.

I have no issue toggling between the Edit bar button and the Done bar button.

However, I am unsure how to toggle between the Back bar button and the Cancel bar button.

Could you guide me on how to achieve this?

This is my code snippet.

class NewViewController: UIViewController {

    @IBOutlet weak var editBarButtonItem: UIBarButtonItem!
    
    private var editMode: Bool = false
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func editButtonClick(_ sender: Any) {
        if editMode {
            editBarButtonItem.title = "Edit"
            
            // TOD: How to provide a back bar button item at top left?
        } else {
            editBarButtonItem.title = "Done"
            
            // TOD: How to provide a "Cancel" bar button item at top left?
        }
        
        editMode.toggle()
    }
    
}

2

Answers


  1. You can programmatically create UIBarButtonItem then set action for it.

        private var editMode = false {
            didSet {
                setEditAction()
                setBackAction()
            }
        }
    
        override func viewDidLoad() {
            ...
            setEditAction()
            setBackAction()
        }
    
        @objc private func toggleEditMode() {
            editMode.toggle()
        }
        
        @objc private func setEditAction() {
            let rightButton = UIBarButtonItem(title: editMode ? "Done" : "Edit", image: nil, primaryAction: nil, menu: nil)
            rightButton.target = self
            navigationItem.rightBarButtonItem = rightButton
            rightButton.action = #selector(toggleEditMode)
        }
        
        private func setBackAction() {
            if editMode {
                let leftButton = UIBarButtonItem(title: "Cancel", image: nil, primaryAction: nil, menu: nil)
                leftButton.target = self
                navigationItem.leftBarButtonItem = leftButton
                leftButton.action = #selector(toggleEditMode)
            } else {
                //set bar button to nil to get normal form back
                navigationItem.leftBarButtonItem = nil
            }
        }
    

    Output here:

    enter image description here

    Login or Signup to reply.
  2. To start, do not create your own Edit/Done button. UIViewController has built-in support for this.

    func viewDidLoad() {
        super.viewDidLoad()
    
        self.navigationItem.rightBarButtonItem = self.editButtonItem
    }
    

    editButtonItem is provided for you. It toggles between "Edit" and "Done". When tapped, it calls the UIViewController method setEditing:animated: and it toggles the isEditing property. All you need to do is override that method to app/remove the "Cancel" button.

    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
    
        if (editing) {
            // Edit has been pressed. Add the Cancel button
            self.navigationItem.setLeftBarButton(UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelHandler)), animated: animated)
        } else {
            // Done has been pressed. Remove the Cancel button and the back button will reappear
            self.navigationItem.setLeftBarButton(nil, animated: animated)
        }
    }
    
    @objc func cancelHandler(_ button: UIBarButtonItem) {
        // handle the Cancel button
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search