iosobjective-ciphonemessageui

Cancel and send button missing on MFMailComposeViewController iOS


I am working on an iOS app where user can email and send sms.I am using MFMailComposeViewController & MFMessageComposeViewController for sending email and SMS but sometimes Cancel and Send button appear over composer and sometime it doesn't appear at all. This issue is random and I have tried alot to figure out. Any help will be greatly appreciated. Code

  MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
  mail.mailComposeDelegate = self;
  [mail setSubject:Email_Subject];
  [mail setMessageBody:Share_Message isHTML:NO];
  [mail setToRecipients:@[@""]];
  [self presentViewController:mail animated:YES completion:NULL];

I have implemented MFMailComposeViewControllerDelegate in my viewController in header file.


Solution

  • OK, I've got some traction on this finally. My problem stemmed in part from me changing nav bar colors in my app delegate (Swift):

        UINavigationBar.appearance().barTintColor = UIColor.black
        UIApplication.shared.statusBarStyle = .lightContent
    
        // To get my hamburger menu white colored
        UINavigationBar.appearance().tintColor = UIColor.white
    

    Due to this, and some interaction with the Zoomed mode (see my comment above), sometimes I'd get the Cancel/Send buttons set to white color in my mail controller. Like this:

    enter image description here

    I'll show you my class (Objective C) that displays the mail controller, which now works for me to solve the problem in this question. Note that the line:

    [UINavigationBar appearance].tintColor = appleBlueTintColor;
    

    is really the secret sauce in all of this:

    #import <MessageUI/MessageUI.h>
    
    @interface SendEmail : MFMailComposeViewController
    
    // Returns nil if can't send email on this device. Displays an alert before returning in this case.
    - (id) initWithParentViewController: (UIViewController *) parent;
    
    // Show the email composer.
    - (void) show;
    
    // Message to append to the bottom of support emails. The string doesn't contain HTML.
    + (NSString *) getVersionDetailsFor: (NSString *) appName;
    
    @end
    
    @interface SendEmail ()<MFMailComposeViewControllerDelegate>
    @property (nonatomic, weak) UIViewController *myParent;
    @property (nonatomic, strong) UIColor *previousBarTintColor;
    @property (nonatomic, strong) UIColor *previousTintColor;
    @end
    
    #import "SendEmail.h"
    #import <sys/utsname.h>
    @implementation SendEmail
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    // Using this init method depends on the `show` method being called immediately after-- to reset the nav bar colors back to what they were originally.
    - (id) initWithParentViewController: (UIViewController *) theParent {
        if (![MFMailComposeViewController canSendMail]) {
            NSString *title = @"Sorry, the app isn't allowed to send email.";
            NSString *message = @"Have you configured this device to send email?";
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
            [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
            [theParent presentViewController:alert animated:YES completion:nil];
            return nil;
        }
    
        // The default app nav bar color is black-- and that looks bad on the mail VC. Need to change and then set back both the barTintColor and the tintColor (in the `show` method).
    
        self.previousBarTintColor = [UINavigationBar appearance].barTintColor;
        self.previousTintColor = [UINavigationBar appearance].tintColor;
    
        [[UINavigationBar appearance] setBarTintColor:[UIColor whiteColor]];
    
        // I got this color from the digital color meter-- this is what it is supposed to be on the Cancel/Send buttons.
        UIColor *appleBlueTintColor = [UIColor colorWithRed:31.0/255.0 green:134.0/255.0 blue:254.0/255.0 alpha:1.0];
        [UINavigationBar appearance].tintColor = appleBlueTintColor;
    
        self = [super init];
        if (self) {
            self.mailComposeDelegate = self;
            self.myParent = theParent;
        }
    
        return self;
    }
    
    - (void) show {
        [self.myParent presentViewController:self animated:YES completion:^{
            [[UINavigationBar appearance] setBarTintColor: self.previousBarTintColor];
            [UINavigationBar appearance].tintColor = self.previousTintColor;
        }];
    }
    
    - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
        [self.myParent dismissViewControllerAnimated:YES completion:nil];
    }
    
    + (NSString *) getVersionDetailsFor: (NSString *) appName;
    {
        NSMutableString *message = [NSMutableString string];
        [message appendString:@"\n\n\n--------------\n"];
        [message appendFormat:@"iOS version: %@\n", [[UIDevice currentDevice] systemVersion]];
        [message appendFormat:@"%@ version: %@ (%@)\n", appName,
         [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"],
         [[NSBundle mainBundle]objectForInfoDictionaryKey:@"CFBundleVersion"]];
        [message appendFormat:@"Hardware: %@\n", [self machineName]];
    
        return message;
    }
    
    // See http://stackoverflow.com/questions/11197509/ios-iphone-get-device-model-and-make
    + (NSString *) machineName;
    {
        struct utsname systemInfo;
        uname(&systemInfo);
    
        return [NSString stringWithCString:systemInfo.machine
                                  encoding:NSUTF8StringEncoding];
    }
    
    @end