Search code examples
iosemailuiviewcontrollermodalviewcontrollermfmailcomposer

MFMailComposeViewController Display Issue from NSObject Class - iOS


I have an issue with MFMailComposeViewController when trying to implement from an NSObject class.

I have used MFMailComposeViewController numerous times without issue, but always within a View Controller.

However, in this case, I make a call to an NSObject Class which will run, whilst the user is normally on one ViewController. However, this code is run from a number of View Controllers, hence the use of the NSObject, and my need to allow the composer to present over ANY view controller.

The issue is that when complete, it needs to throw up an email composer, and I am unable to get this to work. Instead, it never launches the Mail Composer view.

I have the delegate in place, code follows, and the delegate is set within the .h.

MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];

    if([MFMailComposeViewController canSendMail]){
        mc.mailComposeDelegate = self;
        [mc setSubject:emailTitle];
        [mc setMessageBody:messageBody isHTML:NO];
        [mc setToRecipients:toRecipents];

        [[mc navigationBar] setTintColor: [UIColor whiteColor]]; // Text color
        // Present mail view controller on screen
        [self presentViewController:mc animated:YES completion:^{
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
        }];

    }


- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
    switch (result)
    {
        case MFMailComposeResultCancelled:
            // NSLog(@"Mail cancelled");
            break;
        case MFMailComposeResultSaved:
            // NSLog(@"Mail saved");
            break;
        case MFMailComposeResultSent:
            // NSLog(@"Mail sent");
            break;
        case MFMailComposeResultFailed:
            // NSLog(@"Mail sent failure: %@", [error localizedDescription]);
            break;
        default:
            break;
    }

    // Close the Mail Interface

    [self dismissViewControllerAnimated:YES completion:NULL];

}

I have also tried to shift the code to AppDelegate, and use a notification from the NSObject class to fire the composer, however, using this method I find that the composer WILL display over a pushed VC, but if a modal view is currently displaying, it does NOT display the composer.

Finally, I tried adding an entirely separate view controller, adding the mail composer to it, and adding this via AppDelegate, but this too will only display over a pushed VC, and not a modal VC.

My thinking is that I need to find the 'top' of the navigation stack, in order to display the composer above this, but I am not 100% sure.

I would welcome comments from anyone who is able to throw any light on how I can achieve this, as I feel sure it must be possible, as I AM able to add the MailController to a modal view if the code is within the View Controller itself, but clearly this would mean I would need to add such said code to multiple VC's, which, whilst I could, seems to be an odd way to have to proceed.

Thanks all!


Solution

  • I thought I would come back and answer this!

    The MFMailComposeViewController must be launched within a ViewController. This is by design.