2

I have a question similar to this question but it is MonoTouch specific. When I need to call NavigationController.PopToRootViewController(), I'm currently on the 8th view controller on the stack and I need to clean up a bunch of stuff (references, events, images, etc.) on all the view controllers that get popped off, how would I do this?

Community
  • 1
  • 1
Andrew Young
  • 1,779
  • 1
  • 13
  • 27

3 Answers3

2

To achieve this, I tend to subclass UINavigationController, so that I can intercept all calls to popToRootViewController after it's sent to the superview.

popToRootViewController returns an NSArray * containing all UIViewControllers that have been popped off the stack, so you can send cleanup messages to them. For example:

@interface BCNavigationController : UINavigationController 
@end

@implementation BCNavigationController


- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated {
    NSArray * poppedControllers =  [super popToRootViewControllerAnimated:animated];
    [self sendPoppedMessageToControllers:poppedControllers];
    return poppedControllers;
}

- (UIViewController *) popViewControllerAnimated:(BOOL)animated {
    UIViewController * poppedController = [super popViewControllerAnimated:animated];
    [self sendPoppedMessageToControllers:[NSArray arrayWithObject:poppedController]];
    return poppedController;
}

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated {
    NSArray * poppedControllers =  [super popToViewController:viewController animated:animated];
    [self sendPoppedMessageToControllers:poppedControllers];
    return poppedControllers;
}

- (void) sendPoppedMessageToControllers:(NSArray *)controllers {
    for (UIViewController * controller in controllers )
    {
        if ([controller respondsToSelector:@selector(viewWasPoppedOffStack)])
            [controller performSelector:@selector(viewWasPoppedOffStack)];
    }
}

@end

...then, in your child UIViewController

// MyViewController.m
- (void) viewWasPoppedOffStack  {

// do some cleanup

}
Carlos P
  • 3,928
  • 2
  • 34
  • 50
1

You need to implement UIViewController.viewDidUnload() method, it's called when popping down views to root or precedent view. To make you application lighter, you could manage some of your controller items in UIViewController.View[Will|Did]Disappear() too, but you must be careful with them, because they're also called when pushing another view onto the current one, so take care to not clean items you rely on when your view pops back.

psycho
  • 631
  • 10
  • 27
  • 1
    I think there's some confusion around when viewDidUnload gets called. According to the [iOS](http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIViewController_Class/Reference/Reference.html) docs it only gets called during low-memory situations. I verified that unload doesn't always get called when views are popped off the stack. Unload actually isn't explicit to the UINavigationController. – Andrew Young Sep 07 '11 at 00:09
  • You are right `Andrew Young`, There is no guarantee that `viewDidUnload` calls every time you pop from the navigation controller. – geekay Mar 21 '12 at 09:02
  • Thanks for these precisions, I'd have sworn it was called every time, but it may have been a matter of coincidences. I'll be more careful 'bout that on future developments, thank you two! – psycho Mar 21 '12 at 13:40
1

I ended up implementing a Cleanup() method on each view controller. Set up the view controllers to observe for a certain notification from the NSNotification.DefaultCenter. When time comes to call PopToRootViewController() then post that notification event. View controllers observing this notification would be set to run Cleanup() which would safely clean up all refs and memory.

Andrew Young
  • 1,779
  • 1
  • 13
  • 27
  • 1
    If you subclass UINavigationController, then you can intercept all calls to popToRootViewController before, or after the method is called. It's worth remembering that popToRootViewController returns an NSArray * containing all viewControllers that were popped off the stack, so you can send cleanup messages to them. See my answer below. – Carlos P Jun 20 '12 at 10:19