How to clean up view controllers after calling PopToRootViewController?
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?
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
}
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.
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.
精彩评论