Possible Duplicate:
Call Function in Underlying ViewController as Modal View Controller is Dismissed
I've tried almost everything. Here's what I've tried:
-(void)viewWillAppear:(BOOL)animated { NSLog(@"Test"); } -(void)viewDidAppear:(BOOL)animated { NSLog(@"Test"); } -(void)viewDidLoad { NSLog(@"Test"); }
Why are none of these working in my parent view controller when the modal view controller is dismissed? How can I get this to work?
According to the View Controller Programming guide for iPhone OS, this is incorrect when it comes to dismissing modal view controllers you should use delegation. So before presenting your modal view make yourself the delegate and then call the delegate from the modal view controller to dismiss.
The block to execute after the view controller is dismissed. This block has no return value and takes no parameters.
This answer was rewritten/expanded to explain the 3 most important approaches (@galambalazs)
The simplest approach is using a callback block
. This is good if you only have one listener (the parent view controller) interested in the dismissal. You may even pass some data with the event.
In MainViewController.m
SecondViewController* svc = [[SecondViewController alloc] init]; svc.didDismiss = ^(NSString *data) { // this method gets called in MainVC when your SecondVC is dismissed NSLog(@"Dismissed SecondViewController"); }; [self presentViewController:svc animated:YES completion:nil];
In SecondViewController.h
@interface MainViewController : UIViewController @property (nonatomic, copy) void (^didDismiss)(NSString *data); // ... other properties @end
In SecondViewController.m
- (IBAction)close:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; if (self.didDismiss) self.didDismiss(@"some extra data"); }
Delegation
is the recommended pattern by Apple:
Dismissing a Presented View Controller
If the presented view controller must return data to the presenting view controller, use the delegation design pattern to facilitate the transfer. Delegation makes it easier to reuse view controllers in different parts of your app. With delegation, the presented view controller stores a reference to a delegate object that implements methods from a formal protocol. As it gathers results, the presented view controller calls those methods on its delegate. In a typical implementation, the presenting view controller makes itself the delegate of its presented view controller.
MainViewController
In MainViewController.h
@interface MainViewController : UIViewController <SecondViewControllerDelegate> - (void)didDismissViewController:(UIViewController*)vc; // ... properties @end
Somewhere in MainViewController.m (presenting)
SecondViewController* svc = [[SecondViewController alloc] init]; svc.delegate = self; [self presentViewController:svc animated:YES completion:nil];
Somewhere else in MainViewController.m (being told about the dismissal)
- (void)didDismissViewController:(UIViewController*)vc { // this method gets called in MainVC when your SecondVC is dismissed NSLog(@"Dismissed SecondViewController"); }
SecondViewController
In SecondViewController.h
@protocol SecondViewControllerDelegate <NSObject> - (void)didDismissViewController:(UIViewController*)vc; @end @interface SecondViewController : UIViewController @property (nonatomic, weak) id<SecondViewControllerDelegate> delegate; // ... other properties @end
Somewhere in SecondViewController.m
[self.delegate didDismissViewController:self]; [self dismissViewControllerAnimated:YES completion:nil];
(note: the protocol with didDismissViewController: method could be reused throughout your app)
Another solution is sending an NSNotification
. This is a valid approach as well, it might be easier than delegation in case you only want to notify about the dismissal without passing much data. But it's main use case is when you want multiple listeners for the dismissal event (other than just the parent view controller).
But make sure to always remove yourself from NSNotificationCentre after you are done! Otherwise you risk of crashing by being called for notifications even after you are deallocated. [editor's note]
In MainViewController.m
- (IBAction)showSecondViewController:(id)sender { SecondViewController *secondVC = [[SecondViewController alloc] init]; [self presentViewController:secondVC animated:YES completion:nil]; // Set self to listen for the message "SecondViewControllerDismissed" // and run a method when this message is detected [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didDismissSecondViewController) name:@"SecondViewControllerDismissed" object:nil]; } - (void)dealloc { // simply unsubscribe from *all* notifications upon being deallocated [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)didDismissSecondViewController { // this method gets called in MainVC when your SecondVC is dismissed NSLog(@"Dismissed SecondViewController"); }
In SecondViewController.m
- (IBAction)close:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; // This sends a message through the NSNotificationCenter // to any listeners for "SecondViewControllerDismissed" [[NSNotificationCenter defaultCenter] postNotificationName:@"SecondViewControllerDismissed" object:nil userInfo:nil]; }
Hope this helps!
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