The root view controller is simply the view controller that sits at the bottom of the navigation stack. You can access the navigation controller's array of view controllers through its viewControllers property. To access the root view controller, we ask for the first item of the array of view controllers.
In the Storyboard, select the view controller that you want to instantiate in code. Make sure the yellow circle is highlighted, and click on the Identity Inspector. Set the custom class as well as the field called "Storyboard ID". You can use the class name as the Storyboard ID.
You can use the following.
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSArray *viewControllers = self.navigationController.viewControllers;
if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
// View is disappearing because a new view controller was pushed onto the stack
NSLog(@"New view controller was pushed");
} else if ([viewControllers indexOfObject:self] == NSNotFound) {
// View is disappearing because it was popped from the stack
NSLog(@"View controller was popped");
}
}
This is, of course, possible because the UINavigationController's view controller stack (exposed through the viewControllers property) has been updated by the time that viewWillDisappear is called.
I think the easiest way is:
- (void)viewWillDisappear:(BOOL)animated
{
if ([self isMovingFromParentViewController])
{
NSLog(@"View controller was popped");
}
else
{
NSLog(@"New view controller was pushed");
}
[super viewWillDisappear:animated];
}
Swift:
override func viewWillDisappear(animated: Bool)
{
if isMovingFromParent
{
print("View controller was popped")
}
else
{
print("New view controller was pushed")
}
super.viewWillDisappear(animated)
}
From Apple's Documentation in UIViewController.h :
"These four methods can be used in a view controller's appearance callbacks to determine if it is being presented, dismissed, or added or removed as a child view controller. For example, a view controller can check if it is disappearing because it was dismissed or popped by asking itself in its viewWillDisappear: method by checking the expression ([self isBeingDismissed] || [self isMovingFromParentViewController])."
- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);
- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);
So yes, the only documented way to do this is the following way :
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self isBeingDismissed] || [self isMovingFromParentViewController]) {
}
}
Swift 3 version:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if self.isBeingDismissed || self.isMovingFromParentViewController {
}
}
If you just want to know whether your view is getting popped, I just discovered that self.navigationController
is nil
in viewDidDisappear
, when it is removed from the stack of controllers. So that's a simple alternative test.
(This I discover after trying all sorts of other contortions. I'm surprised there's no navigation controller protocol to register a view controller to be notified on pops. You can't use UINavigationControllerDelegate
because that actually does real display work.)
Swift 4
override func viewWillDisappear(_ animated: Bool)
{
if self.isMovingFromParent
{
//View Controller Popped
}
else
{
//New view controller pushed
}
super.viewWillDisappear(animated)
}
In Swift:
override func viewWillDisappear(animated: Bool) {
if let navigationController = self.navigationController {
if !contains(navigationController.viewControllers as! Array<UIViewController>, self) {
}
}
super.viewWillDisappear(animated)
}
I find Apple's documentation on this is hard to understand. This extension helps see the states at each navigation.
extension UIViewController {
public func printTransitionStates() {
print("isBeingPresented=\(isBeingPresented)")
print("isBeingDismissed=\(isBeingDismissed)")
print("isMovingToParentViewController=\(isMovingToParentViewController)")
print("isMovingFromParentViewController=\(isMovingFromParentViewController)")
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With