We are building a journey where we need a View Controller to remove the Controller that came before it in the stack.
When we land on that View Controller it will be the 3rd controller in the stack and we need it to remove the Controller that is second (i.e. the Controller that is at index 1).
In ViewDidLoad we tried doing this by getting the current array of View Controllers from the Navigation Controller, removing the Controller at index 1 and then calling SetViewControllers. However when the back button is pressed we end up going back to the View Controller that was supposed to be removed.
If instead we call removeFromParentViewController on the View Controller to be removed then we get the behaviour we expected.
What are the differences between these two approaches? What would cause a View Controller to remain in the stack despite it not being in the array passed to SetViewControllers?
Related
I'm trying to present a view controller that will be kept displayed above everything, regardless of the currently presented view controller, so it will be kept as displayed even if the view controller behind it will get dismissed, or starts to present another view controller.
I know how to find the topmost view controller (for example as suggested here) but in this case presenting over this view controller will make the new view controller depends on the hierarchy of the parent controller, which I try to avoid.
Present the view from the rearmost view, the window. But give it a high z index so that it shows up in front of everything else.
I created two view controllers like
Navigation controller -> View Controller -> Details View Controller
1 2 3
The (2) View Controller has a button in it which when clicked will shows (3) Details View Controller. I have created a segue from button to (3) VC.
I have added deinit blocks in those two classes.
deinit {
print("vc deinit")
}
However, this does not get logged. When will a view controller get deallocated?
Sample code
In this case, the only deinit will get called is the second one (the one implemented in the Details View Controller) each time you tap the back button on the navigation (pop to the previous view controller).
So, why the first deinit (the one in the View Controller) didn't get called?
That's because it is the first view controller in the navigation controller stack. Pushing to the second view controller does not mean that the previous one(s) one has been deallocated and still exists as the first element in the navigation stack; As an example, that's why viewDidLoad method should not get called when you come back from a popped view controller, which means it did not get deallocated.
In other words, if I perform a show, I can expect:
the new view will be put on top of the stack?
once the new view unwinds, the new view will be destroyed?
if you unwind back to the initial, then all views will be destroyed except the initial view?
"Show" segue, new in iOS 8, is simply a shorthand for calling UIViewController's showViewController:sender:, which is documented here:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/occ/instm/UIViewController/showViewController:sender:
And, for UINavigationController, here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/#//apple_ref/occ/instm/UINavigationController/showViewController:sender:
As you can see simply by reading the docs, if the view controller in question is the child of a navigation controller, and we are not in a split view controller situation, this method is identical to calling pushViewController:animated: on the navigation controller. Thus, in such a situation, the "show" segue is identical to the "push" segue from previous iOS versions.
I have a tab bar controller with multiple view controllers.
I attempt to do a method call to one of the view controllers (lets call it SomeViewController) and I realised that SomeViewController was not initialised yet.
And SomeViewControllerwill only be initialised when I click it's tab once.
So, is it possible to initialise the view controller even before the view of initialise is presented the first time?
I am trying to make a container view controller that works similarly to navigation controller. When I add something to the stack what do I do with the view controller that is a already there?
It is still my child but I don't want it's view in the view hierarchy. Should I call removeFromParentViewController on it, and just keep a separate stack with it, in that stack? So when the view above is popped off, I can check what view I should push back in order to go back to previous one.
Or should I just remove its view, without removeFromParentViewController call, and add another child controller, and its view to container view hierarchy?
Basically what do I do with the controllers that aren't on the screen?
The "stack" is just an array that a navigation controller uses to keep track of its view controllers. If you're building your own, you will need to have an array also. The way a navigation controller works, when a controller is pushed, that controller is added to the array, and if one is popped, that one is removed from the array. When you do a transition, the one that's going off screen should call removeFromParentViewController, so it's no longer in the hierarchy (but if it's going away because of another one being pushed, you would leave it in your array -- that's how the controller knows which one to go back to on a pop). You should use transitionFromViewController:toViewController:duration:options:animations:completion: to do your transitions from one controller to the next.