iOS: Dismissing and Presenting ModalViewController without access to its Parent ViewController

18,896

Solution 1

Your code looks like it should work. If you are using iOS 5 there is a UIViewController property called presentingViewController.

@property(nonatomic, readonly) UIViewController *presentingViewController;

So you can use this property to get the view controller that presented your modal controller.

Note: In iOS 4 parentViewController would be set to the presenting controller, so if you are supporting both iOS 4 and 5 you will have to check the OS version first to decide which property to access. In iOS 5 Apple have fixed this so that parentViewController is now exclusively used for the parent of contained view controllers (see the section on Implementing a Container View Controller in the UIViewController documentation).

Edit: Regarding accessing self.presentingViewController from within the block: By the time the block is called (after the modal view controller is dismissed) the presentingViewController property may get set to nil. Remember that self.presentingViewController inside the block gives the value of the property when the block is executed, not when it was created. To protect against this do the following:

UIViewController* toPresentViewController = [[UIViewController alloc] init];
UIViewController* presentingViewController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^
{
    [presentingViewController presentModalViewController:toPresentViewController animated:YES];
}];

This is necessary not because self is gone/dismissed (it is safely retained by the block), but because it is no longer presented, therefore its presentingViewController is now nil. It is not necessary to store the presentingViewController anywhere else, the local variable is fine because it will be retained by the block.

Solution 2

Try the following code:

[self dismissViewControllerAnimated:NO 
                         completion:^{
  // instantiate and initialize the new controller
  MyViewController *newViewController = [[MyViewController alloc] init];
  [[self presentingViewController] presentViewController:newViewController
                                                animated:NO
                                              completion:nil];
}];

Solution 3

You could accomplish this using notifications.

For example, fire this notification from outside the modal view when you want it to be dismissed:

[[NSNotificationCenter defaultCenter] postNotificationName:@"dismissModalView" 
                                                    object:nil 
                                                  userInfo:nil];

And then handle that notification inside your modal view:

- (void)viewDidLoad {
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(dismissMe:)
                                                 name:@"dismissModalView" 
                                               object:nil];
}

- (void)dismissMe:(NSNotification)notification {
    // dismiss it here.
}

Solution 4

the solution for ios5:

-(void)didDismissModalView:(id)sender {

   // Dismiss the modal view controller
   int sold=0;

   if(sold==0){

      //Cash_sold.delegate = self;
      // Cash_sold.user_amount.text=[NSString stringWithFormat:@"%d",somme];

      Cash_sold = [[CashSoldview alloc] initWithNibName:@"CashSoldview" bundle:nil];
      CGRect fram1 = CGRectMake(200,20,400,400);
      Cash_sold.view.superview.frame = fram1;
      Cash_sold.view.frame=fram1;
      Cash_sold.modalTransitionStyle= UIModalTransitionStyleCoverVertical;
      Cash_sold.modalPresentationStyle=UIModalPresentationFormSheet;

      UIViewController* presentingViewController = self.parentViewController;

      [self dismissViewControllerAnimated:YES completion:^
      {
         [presentingViewController presentModalViewController:Cash_sold animated:YES];
      }];     
   }
}
Share:
18,896
Byte
Author by

Byte

A simple person in a complicate time.

Updated on June 13, 2022

Comments

  • Byte
    Byte almost 2 years

    Background: I would like to dismiss a modalView that I have presented earlier and right away present the same viewController that I just dismissed with new information.

    Problem: I have not been very successful in doing so without an explicit pointer to the parent ViewController that presented the first ViewController modally. I am trying to write this class that works without messing around with the previous viewController's code.

    Possible lead: There are couple of things I have been experimenting with:

    1.) Trying to get access to the parent ViewController, which at this time I don't know how to.

    2.) Once access to the parent is gained, I can simply apply the following code:

    UIViewController* toPresentViewController = [[UIViewController alloc] init];
        [self dismissViewControllerAnimated:YES completion:^{
            [parentViewControllerAccessor presentModalViewController:toPresentViewController animated:YES];
    }];
    

    In theory this should work given the access to parent viewController. I am open to other ways of doing this.

    Assumption: You do not have permission to change any code in the parent ViewController.