How to reliablly detect that a UIViewController has been dismissed

6.3k views Asked by At

I need to do things when a ViewController is dismissed, ie:

  • When “Back” is pressed
  • When popToRootViewController is called by a parent if was in a UINavigationController
  • when DismissViewController is called by a parent if it was presented

eg I need to unsubscribe from events, or dimiss a presented alert etc.

ViewWillDisappear is not called when popToRootViewController is called by it’s parent so that doesnt work.

WillMoveToParentViewController is only for View Controller containment

Dealloc is no good as that is only when garbage collected. I’m using c# Xamarin anyway and it doesnt work there.

ViewDidUnload is no longer used and was never for this anyway

A ViewController itself should not care how it was presented so how do we find out when it is dismissed?

This seems like an important, basic requirement. How do we unsubsribe to events from a model without this, for example?

This is a similar question, but no good answer:

Can you detect when a UIViewController has been dismissed or popped??

4

There are 4 answers

1
JordanMazurke On

When using a UINavigationController it is available through the NavigationController property on the UIViewController (or equivalent) subclass object.

The ViewWillDisappear(bool animated) and ViewDidDisappear(bool animated) will be called when a new UIViewController is loaded onto the UINavigationController stack.

It may help if you utilise the storyboard functionality within Xamarin Studio as the NavigationController->UIViewController relationship is visually represented.

If you are having further trouble please post sample code in order for the community to review further.

0
Dancreek On

This question is a bit old but here is the conclusion I came to:

-dealloc - no guarantees on when this is going to get called. Good for boilerplate code but not reliable.

-viewDidDisappear & -viewWillDisappear are only called when the view stops being visible (imagine that ;) ). So they are ok when popping one view at a time but not for popToRoot or popping back several controllers at a time

-willMoveToParentViewController should work (viewControllers in a UINavigation Controller are contained by that controller) but for some reason I'm seeing inconsistencies on when this gets called or not.

-didMoveToParentViewController - does get called on every viewController being dismissed from the navigation stack. So... this looks like the most reliable place to do this.

0
scosman On

I like this approach. The beingDismissed guard prevents calling if something is getting pushed over us, and only fires when we're being dismissed.

-(void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    
    // check we're being dismissed
    if (self.beingDismissed) {
        // Action here!
    }
}
0
Lee Probert On

I have called presentingViewController.viewWillAppear from my modal to let it know it's being dismissed.