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
VRAwesome :
Just implement MFMailComposeViewController delegate method this way.\n\n - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error\n{\n switch (result)\n {\n case MFMailComposeResultCancelled:\n NSLog(@\"Mail cancelled: you cancelled the operation and no email message was queued.\");\n break;\n case MFMailComposeResultSaved:\n NSLog(@\"Mail saved: you saved the email message in the drafts folder.\");\n break;\n case MFMailComposeResultSent:\n NSLog(@\"Mail send: the email message is queued in the outbox. It is ready to send.\");\n break;\n case MFMailComposeResultFailed:\n NSLog(@\"Mail failed: the email message was not saved or queued, possibly due to an error.\");\n break;\n default:\n NSLog(@\"Mail not sent.\");\n break;\n }\n [[controller presentingViewController] dismissViewControllerAnimated:YES completion:^{\n\n if (result == MFMailComposeResultSent)\n {\n [self dismissViewControllerAnimated:YES completion:nil];\n }\n }];\n\n\n}",
2014-07-09T07:17:34