简体   繁体   中英

Dismissing modal view controller in another modal view controller

My iPad app presents a modal view controller from which the user can choose to send an email. My issue is that this opens a new modal view controller (MFMailComposeViewController) , which I then can't seem to dismiss properly. This SO thread describes a similar issue, but none of the suggestions in that thread worked for me.

My initial view controller brings up the modal VC using a storyboard segue:

[self performSegueWithIdentifier:@"mySegue" sender:self];

The modal view controller calls the following method when a UIButton is pressed to bring up the iOS default mail composer VC:

- (IBAction)sendWithMail
{
    MFMailComposeViewController *composeMail = [[MFMailComposeViewController alloc] init];

    composeMail.mailComposeDelegate = self.presentingController;

    [self presentViewController:composeMail animated:YES completion:NULL];
}

Here, self.presentingController is a reference to the initial view controller, which conforms to the <MFMailComposeViewControllerDelegate> protocol. When the user has finished writing the email, the delegate method in my initial VC is called. Now I need to close the mail composer view controller and/or my own modal view controller, depending on the result. So I wrote a method in the initial VC like this:

- (void)mailComposeController:(MFMailComposeViewController *)controller
          didFinishWithResult:(MFMailComposeResult)result
                        error:(NSError *)error
{

    [controller dismissViewControllerAnimated:YES completion:NULL];

    switch (result)
    {
        case MFMailComposeResultCancelled:
        {
            break;
        }
        case MFMailComposeResultSaved:
        {
            [self updateStatusMessage:@"Mail saved."];
            break;
        }
        case MFMailComposeResultSent:
        {
            [self updateStatusMessage:@"Mail sent."];
            [self dismissViewControllerAnimated:YES completion:^{}];
            break;
        }
        case MFMailComposeResultFailed:
        {
            [self updateStatusMessage:@"Mail failed."];
            break;
        }
        default:
        {
            break;
        }
    }
}

The idea is that the mail composer should always close, but the modal view controller should close only if the mail was sent successfully. But this doesn't work: when the mail is sent, the app crashes. The only log output is (lldb) and Xcode highlights the return line of main.m in green with Thread 1: EXC_BAD_ACCESS (code=1, address=...) .

If I don't try to close the mail composer, and just call [self dismissViewControllerAnimated:YES completion:^{}]; regardless of the result, then both the composer and my modal view controller close and there is no problem. But this is not the behaviour I want.

I've also tried self.presentingViewController instead of just self in the dismiss calls, but that doesn't help.

I feel like I'm missing something fundamental about how view controllers interact, but I can't figure it out. Any help is appreciated!

iOS 7 + Xcode 5

Just implement MFMailComposeViewController delegate method this way.

 - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
    switch (result)
    {
        case MFMailComposeResultCancelled:
            NSLog(@"Mail cancelled: you cancelled the operation and no email message was queued.");
            break;
        case MFMailComposeResultSaved:
            NSLog(@"Mail saved: you saved the email message in the drafts folder.");
            break;
        case MFMailComposeResultSent:
            NSLog(@"Mail send: the email message is queued in the outbox. It is ready to send.");
            break;
        case MFMailComposeResultFailed:
            NSLog(@"Mail failed: the email message was not saved or queued, possibly due to an error.");
            break;
        default:
            NSLog(@"Mail not sent.");
            break;
    }
    [[controller presentingViewController] dismissViewControllerAnimated:YES completion:^{

        if (result == MFMailComposeResultSent)
        {
            [self dismissViewControllerAnimated:YES completion:nil];
        }
   }];

}

- (void)mailComposeController:(MFMailComposeViewController *)controller
          didFinishWithResult:(MFMailComposeResult)result
                        error:(NSError *)error
{


    switch (result)
    {
        case MFMailComposeResultCancelled:
        {
            break;
        }
        case MFMailComposeResultSaved:
        {
            [self updateStatusMessage:@"Mail saved."];
            break;
        }
        case MFMailComposeResultSent:
        {
            [self updateStatusMessage:@"Mail sent."];
          [self dismissViewControllerAnimated:YES completion:nil];
            break;
        }
        case MFMailComposeResultFailed:
        {
            [self updateStatusMessage:@"Mail failed."];
            break;
        }
        default:
        {
            break;
        }
    }

              [self dismissViewControllerAnimated:YES completion:nil];

}

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM