2
votes

I use MFMailComposeViewController to send mail in my app. But when present mail compose view controller, all of navigation buttons are disabled (except back button in select mail address screen), i must use Home button to quit app. Does anyone has idea? Here is screen shot: Screen shot2


Code:

- (void)shareVieEmail
{
    if ([MFMailComposeViewController canSendMail]) {
        MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
        mailViewController.mailComposeDelegate = self;
        [mailViewController setSubject:@"Test subject"];
        [mailViewController setMessageBody:@"Mail message body" isHTML:NO];

        NSData *imageData = [NSData dataWithContentsOfFile:photourl];
        [mailViewController addAttachmentData:imageData mimeType:@"image/jpg" fileName:@"example_photo"];
        [self presentModalViewController:mailViewController animated:YES];
    } else {
        [[[UIAlertView alloc] initWithTitle:@"Cannot send mail" message:@"Device is unable to send email in its current state" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show];
    }
}

Delegate method :

- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
    switch (result)
    {
        case MFMailComposeResultCancelled:
            //NSLog(@"Result: canceled");
            break;
        case MFMailComposeResultSaved:
            //NSLog(@"Result: saved");
            break;
        case MFMailComposeResultSent:
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Result" message:@"Mail Sent Successfully" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
            [alert show];
        }
            break;
        case MFMailComposeResultFailed:
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Result" message:@"Mail Sent Failed" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
            [alert show];
        }
            break;
        default:
            //NSLog(@"Result: not sent");
            break;
    }
    if (error) {
        [[[UIAlertView alloc] initWithTitle:@"Cannot send mail" message:[NSString stringWithFormat:@"ERROR:%@", [error userInfo]] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show];
    }
    [self dismissModalViewControllerAnimated:YES];
}

And in header file, I declared implement MFMailComposeViewControllerDelegate.

3
can you show the code used to present the controller?mvds
strange, it looks fine. Could it have something to do with you email settings? Does it look like this on all devices?mvds
@mvds, it happened on both simulator and device. Sample project of Apple worked fine.youshunei
Are you aware that you are leaking an instance of MFMailComposeViewController every time you present one? Could be problematic if the first instance somehow holds a lock of some kind, preventing a second instance to acquire one. Add a line [mailer autorelease]; somewhere, remove app and reinstall.mvds
At moment, I using ARC support to compile project (no need autorelease, retain,.. while coding), I thinks it isn't root cause. However, I'll try compile only this file with no ARC support.youshunei

3 Answers

2
votes

I had exactly the same problem. and it took me a while to figure this out but no surprise it came down to customized UIBarButtonItem

I bet in your UIBarButtonItem.h there is a method

-(void)setEnabled:(BOOL)enabled ;

and the implementation looks like this:

-(void)setEnabled:(BOOL)enabled {
    if (self.customView) {
        if ([[self.customView.subviews objectAtIndex:0] isKindOfClass:[UIButton class]])         {
            ((UIButton*)[self.customView.subviews objectAtIndex:0]).enabled = enabled;
        }
    }
}

and this is causing problem so as soon as you comment out this method your problem should go away.

0
votes

I also had this problem, but it my case it was because I had overridden setNavigationBarHidden:animated: from UINavigationController as proposed in this workaround for a bug in CNContactViewController. One solution that would still include the workaround and solve the problem in MFMailComposeViewController would be to use method swizzling to be able to call either the original method or the overridden one, depending on the class of the current topViewController.

0
votes

In your MFMailComposeViewController's delegate you need to implement didFinishWithResult: and dismiss the modal view controller from there.

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{ 
    // you can test the result of the mail sending here if you want

    [self dismissModalViewControllerAnimated:YES];
}

For swift 4.0+

func mailComposeController(controller: MFMailComposeViewController,
                           didFinishWithResult result: MFMailComposeResult, error: NSError?) {
    // Check the result or perform other tasks.

    // Dismiss the mail compose view controller.
    controller.dismissViewControllerAnimated(true, completion: nil)
}