[SWIFT] I want to go back to a specific VC by tapping the back button on the NavigationBar!

TL;DR

Just remove the VC in the middle from the stack.

Main story

For example, have you ever thought about this? First, the Push transition from screen A to screen B, and then from screen B to screen C with the same Push transition. After that, I want to skip B and return directly to screen A by returning from screen C! Often, for example, when screen B is a two-step verification screen, in this case when returning from screen C, it is nonsense to return to the two-step verification screen, so when you want to skip that screen and return to the previous screen. ..

[No effect] Customize backBarButtonItem

The first thing you can think of is customizing the back button on the NavigationBar and running navigationController? .PopToViewController yourself when this button is tapped. But unfortunately, the navigationbar's back button is backBarButtonItem instead of leftBarButtonItem. You can't customize the behavior of this button.

that? No? navigationItem.backBarButtonItem supports{get set}, right?

Yes, it is. However, what you can set here is the back button when you move to the next screen. In other words, this is the setting when the return destination is yours. In addition, setting action to backBarButtonItem will be ignored by UIKit. Only the display of backBarButtonItem can be set here.

By the way, there are some articles that it fits UINavigationControllerDelegate and you can customize the behavior of the back button by setting navigationController? .Delegate to yourself, but that is a lie. can not. In the first place, UINavigationControllerDelegate is not responsible for customizing the transition destination.

[Not good] Set leftBarButtonItem

If you can't customize the back button, the next thing to think about is to replace it with leftBarButtonItem. Sure, this would allow popToViewController to run, so you can go back to a particular VC. However, there are two disadvantages.

The first is that the < mark peculiar to the back button is not displayed. This is a common mark on his UIKit, so removing it would be inconsistent and especially uncomfortable for heavy iOS users. Of course, it is possible to forcibly create and display a < image on your own, but it still feels strange compared to the genuine < mark.

The other is that you cannot return by swiping the edge from the left end. This is also a gesture operation common to his UIKit, and it is one of the specifications that is indispensable especially now that the large screen iPhone has become mainstream. If this disappears, the only way to return to the previous screen is to press the back button on the upper left, which is very difficult to press. Of course, it is possible to implement an edge swipe gesture on your own, but it is still troublesome.

In addition to the above disadvantages, depending on the design, the title of screen A must be set with leftBarButtonItem on screen C, so it is unpleasant to make it slightly Fat.

[Recommended] Delete the screen you want to skip after the transition from the stack

In fact, if you change your approach, this is surprisingly very easy to solve: just remove the screen you want to skip from the navigationController? .ViewControllers array in the first place. In the first place, if you want to skip screen B when you return, you don't need screen B anymore. Then, if you have already transitioned to screen C, if you delete the previous screen B, NavigationBar will set it to return to screen A without permission, so < and screen name display or edge swipe You don't have to do any troublesome work such as setting gestures, so it's very comfortable because it works with a straightforward implementation of UIKit.

ViewControllerB


    navigationController?.pushViewController(vc, animated: true) //Push transition to next screen C
    navigationController?.viewControllers.removeAll(where: { $0 === self }) //Immediately after that it removes itself from the NavigationController's viewControllers stack

screen0.gif

Of course this isn't perfect, there's one subtle issue: the name of screen B appears in place of the back button for a moment right after transitioning to screen C. The display is only for a moment, and when the transition is complete, screen B disappears from the stack and changes to the name of screen A.

[Alternative] Push transition does not occur in the first place

By the way, there is a similar process in Apple's official app, which is where you enter the passcode setting screen from the settings app. This screen also has an authentication process once before entering the passcode setting screen, and when returning, of course, it returns to the setting list screen without going to the authentication screen. So what Apple is doing is that the authentication screen is a modal transition, not a push transition, and once the authentication is successful, the passcode screen is pushed to the passcode screen and the authentication screen is dismissed.

This kind of processing also looks natural without any discomfort, but in the first place, the "transition destination" displayed from the setting list screen is "passcode setting", not "authentication". That's why I don't feel any discomfort even if I make a modal transition on the authentication screen. This is because the user expects the "passcode setting screen" in the "Push transition". However, on the contrary, if he makes a Modal transition while describing the transition destination as "Screen B", he will feel uncomfortable.

Postscript

Even difficult functions can sometimes be solved easily with a slight change in approach.

Recommended Posts

I want to go back to a specific VC by tapping the back button on the NavigationBar!
I want to play a GIF image on the Andorid app (Java, Kotlin)
I want to monitor a specific file with WatchService
I want to simplify the log output on Android
I want to add a delete function to the comment function
Rspec: I want to test the post-execution state when I set a method on subject
I want to use screen sharing on the login screen on Ubuntu 18
I want to make a specific model of ActiveRecord ReadOnly
I want to call a method and count the number
I want to create a form to select the [Rails] category
I want to put the JDK on my Mac PC
I want to give a class name to the select attribute
How to perform a specific process when the back button is pressed in Android Fragment
Implemented a strong API for "I want to display ~~ on the screen" with simple CQRS
I want to recursively search for files under a specific directory
I want to create a chat screen for the Swift chat app!
I want to make a button with a line break with link_to [Note]
[Controller] I want to retrieve the numerical value of a specific column from the DB (my memo)
I want to add a browsing function with ruby on rails
I want to use swipeback on a screen that uses XLPagerTabStrip
I want to limit the input by narrowing the range of numbers
I want to add the disabled option to f.radio_button depending on the condition
[Java] I tried to make a maze by the digging method ♪
[Android] I want to get the listener from the button in ListView
I want to download a file on the Internet using Ruby and save it locally (with caution)
I want to develop a web application!
I want to write a nice build.gradle
I want to display background-ground-image on heroku.
I want to write a unit test!
I want to install PHP 7.2 on Ubuntu 20.04.
I want to get a list of only unique character strings by excluding fixed character strings from the file name
[swift] How to control the behavior when the back button of NavigationBar is pressed
[RxSwift] I want to deepen my understanding by following the definition of Observable
I want to recursively get the superclass and interface of a certain class
I want to sort by tab delimited by ruby
I want to output the day of the week
Set the time of LocalDateTime to a specific time
[Ruby] I want to do a method jump!
I want to var_dump the contents of the intent
I want to simply write a repeating string
I want to design a structured exception handling
I want to truncate after the decimal point
I want to delete files managed by Git
I want to get the value in Ruby
[Ruby] I want to make a program that displays today's day of the week!
[Android Studio] I want to set restrictions on the values registered in EditText [Java]
I want to place RadioButtons in the same RadioGroup at any position on the screen.
How to place a button that does not move by scrolling on TableView etc.
[Rails] I want to display the link destination of link_to in a separate tab
I tried to operate home appliances by holding a smartphone over the NFC tag
# 1_JAVA I want to get the index number by specifying one character in the character string.
I want to hit the API with Rails on multiple docker-composes set up locally
I want to implement it additionally while using kotlin on a site running Java
I want to call a method of another class
[Java] I want to calculate the difference from the date
I want to use NetBeans on Mac → I can use it!
I want to embed any TraceId in the log
I tried to decorate the simple calendar a little
I want to judge the range using the monthly degree
I want to use a little icon in Rails
How to make JavaScript work on a specific page