Usually, the Navigation Controller allows single 'pop's of view controllers in the stack. This works great for master-detail apps and linear workflows.
When one view controller is connected to another in a web-like fashion, things get difficult to manage.
If you want to rely on the automatted management of a view controller stack but go back more than one item at once, have a look at unwind segues: What are Unwind segues for and how do you use them? -- the answer is illustrated really well.
If you can navigate in circles, it gets more intricate. Essentially, your navigation controller would put new objects of already intantiated classes onto the stack to maintain its breadcrumb trail all the way back to the root view controller.
In some cases, this is not desirable. You could use a UINavigationControllerDelegate
which removes items from the stack when certain conditions are met.
Let's say you have 4 view controllers, A--D. The possible connections are: A - B - C - {B,D} - A. From D, when you're finished, you want to unwind to A. From C, you may want to add an additional item at B, but you don't want to keep track of all the B-C-B-C-B-C-... connections. In these cases, altering the navigation controller history is useful and won't break the expected behavior of the "back" button.