Search code examples
objective-cxcodemfmailcomposeviewcontroller

unable to load the mail client in iOS


I noticed that I am using the mail functionality several time so I decided to make an independent Class for functions that get repeated several time instead of copy-pasting the code several times

the class get successfully called and the e-mail function get successfully called as well but the e-mail client of the phone does not appear after the function is called

here is my code

in the main class I do the following call

-(void)emailFunction{
...

CommonlyUsed Email = [[CommonlyUsed alloc] init];
[Email sendMail:receipient :CC :BCC :subject :body];

...
}

in my CommonlyUsed.h I have the following IDEs called :

#import <UIKit/UIKit.h>
#import <MessageUI/MFMailComposeViewController.h>
#import <MessageUI/MessageUI.h>


@interface CommonlyUsed : UIViewController <MFMailComposeViewControllerDelegate>{

in CommonlyUsed.m I have the following :

-(void)sendMail:(NSString*)receipient:(NSString*)cc:(NSString*)bcc:(NSString*)subject:(NSString*)body{

 MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
    [ composer setMailComposeDelegate:self];

 if ( [MFMailComposeViewController canSendMail]){
if (receipient) {
            [composer setToRecipients:[NSArray arrayWithObjects:receipient, nil]];
        }

        if (cc) {
            [composer setCcRecipients:[NSArray arrayWithObjects:receipient, nil]];
        }

        if (bcc) {
            [composer setBccRecipients:[NSArray arrayWithObjects:receipient, nil]];
        }

        if (subject) {
             [composer setSubject:subject];
        }

 [composer setMessageBody:body isHTML:HTMLBody];

        [composer setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];

        [self presentModalViewController:composer animated:YES];
        }
}

- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
    if(error){
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"error" message:[NSString stringWithFormat:@"error %@", [error description]] delegate:nil cancelButtonTitle:@"dismiss" otherButtonTitles:nil, nil];
        [alert show];
        [self dismissModalViewControllerAnimated:YES];
    }
    else{
        [self dismissModalViewControllerAnimated:YES];
    }

    }

the code compiles and runs without errors what am I missing ??


Solution

  • Instead of doing this:

    [self presentModalViewController:composer animated:YES];

    do this:

    [[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentModalViewController:composer animated:YES];

    or this:

    [[[[UIApplication sharedApplication] keyWindow] rootViewController] presentModalViewController:composer animated:YES];

    Your class Email is not currently an active view controller so it can't present a modal view controller, you need to use an active one, like the rootViewController of the main UIWindow.

    EDIT:

    If your using ARC by the time the emailClient gets dismissed your object(delegate) would have been removed from memory, so a solution is to make the CommonlyUsed class a Singleton:

    +(CommonlyUsed *)sharedInstance {
    
        static CommonlyUsed * cu = nil;
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
    
            cu = [[CommonlyUsed alloc] init];
    
        });
    
        return cu;
    }
    

    So you would use it this way:

    CommonlyUsed * email = [CommonlyUsed sharedInstance];
    [email sendMail:receipient :CC :BCC :subject :body];