We're trying to figure out how to conditionally exclude certain screens in our back-stack when navigating backwards. For instance, take the following screens:
- Main Dashboard (You can go to 2 or 3 from here)
- Order Management (you can go to 3 or 6 from here)
- Enter Order
- Review Order
- Order Confirmation (if you make it here, back should skip 3 & 4)
- Order Status (if you make it here, back should skip 5 (it already skips 3 & 4))
Screens 3-5 represent entering an order so if you've made it to the confirmation page, we don't want you going back to the review or edit pages.
For the same reason, if you've navigated to 'Order Status' from the confirmation page, we don't want you navigating back to the 'Order Confirmation', but rather back to 'Order Management' or 'Main Dashboard' (depending on how you got there)
Note: We're aware of popToViewController and how it lets you skip over all controllers between where you are and the one you specify. The issue is I don't know what that view controller is. I only know which I want to skip over (if they are present.) More importantly, the back button reflects what's in the stack, not what I'm popping to. That's why I'm hoping to tell the system 'Just ignore these in the stack when going back'. Hope that makes sense.
My crude attempt is to modify the back stack like so...
func showConfirmation() {
guard navigationController = navigationController else {
return
}
navigationController.pushViewController(orderConfirmation, animated:true)
if let orderEntryIndex = navigationController.viewControllers.index(of:orderEntry),
let orderReviewIndex = navigationController.viewControllers.index(of:orderReview){
navigationController.viewControllers.removeSubrange(orderEntryIndex...orderReviewIndex)
}
}
func showStatus() {
guard navigationController = navigationController else {
return
}
navigationController.pushViewController(orderStatus, animated:true)
if let orderConfirmationIndex = navigationController.viewControllers.index(of:orderConfirmation){
navigationController.viewControllers.remove(at: orderConfirmationIndex)
}
}
Note: This is simplified code. We don't actually hang onto instances of the view controllers. We find the indexes by looking for their type in the back-stack. This is for simple illustrative purposes only.
While the navigation works, during the animation, the back button shows the original back location, then after the animation, the label's value 'snaps' to show the new back location. This of course proves this isn't the right approach.
I know there are unwind segues, but that worries about where you're going. We just want to remove items from the backlog after navigating away from them, but otherwise leave the back-stack intact.
So how does one achieve this behavior of ignoring prior steps?