How To Implement A Back Button With A Call To Action Logic In A Navigation Controller

Have you encountered a use case where your app user enters a flow in a navigation controller, and once he wants to go back you want to prompt him with a call-to-action alert before he quits the flow?

Here is an example of the use case flow:

1- User enters a signup flow
2- At some step, the user retracts and click on the back button to quit.
3- Since going back means the flow state will be lost, you want to prompt the user with a confirmation alert before the app pops/dismisses the navigation controller.

Normally, clicking on the back button on a navigation controller stack will not wait until we can display an alert asking for a call-to-action. But in some cases, like the one above, we need to make the navigation controller wait before allowing it to pop the view.

The purpose of this quick tutorial is to show you how to implement this feature and enhance your app user experience.

Without further ado, download the started project here and let’s get started.

The project already contains a navigation controller set up for us in storyboard.

Also, the navigation controller bar already implements a back button by default that enable to dismiss the view automatically and move to the previous screen.

From the Project navigator, select SecondViewController.swift and add the following code to the viewDidLoad method:

let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItem.Style.plain, target: self, action: nil)
self.navigationItem.leftBarButtonItem = cancelButton

We just added a UIBarButtonItem to the navigation bar. By leveraging the navigationItem UINavigationItem class we can access the navigation bar appearance and set a custom button to the left item.

Now we have a custom navigation button, we just need to add the call-to-action logic. Also, since dismissing the view is no longer handled automatically for us, we need to explicitly dismiss the view.

Change the cancelButton initialisation we just implemented earlier to the following:

let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItem.Style.plain, target: self, action: #selector(cancelAction))

This will attach a function to the button click action. Next implement the cancelAction method:

@objc func cancelAction() {
   let alert = UIAlertController(title: "Confirmation", message: "Are you sure you want to quit?", preferredStyle: .alert)
   alert.addAction(.init(title: "Cancel", style: .cancel))
   let destructiveActionHandler = UIAlertAction(title: "Yes", style: .destructive) { [weak self] _ in
       self?.navigationController?.popViewController(animated: true)
   }
   alert.addAction(destructiveActionHandler)
   present(alert, animated: true)
}

Re-run the app, the cancel button action will display a prompt and asks for user confirmation. Once validated, the view will then be dismissed from the navigation controller stack and the user is moved back to the previous screen.

That’s it. You can download the final project here.

Conclusion

This use case is frequently encountered, especially in critical and long workflows where user data is entered and saved in the fly (signup flow for example). Knowing how to allow the user to consciously exit such flow is critical to make your app experience better.

Thanks!

Malek
iOS developer with over than 11 years of extensive experience working on several projects with different sized startups and corporates.