MFMailComposeViewController's Cancel Button (action sheet possibly) freezes the view
Asked Answered
E

6

14

I've seen several questions before such as this but for the lack of an accepted answer as well as having implemented everything as needed I still continue to face the issue as follows: I display the mail composer but on clicking cancel, the composer view freezes. I think this is due to the Save/Delete draft action sheet showing up out of the visible frame. Yes I have set the mailComposeDelegate to the presenting view controller and have read up on several similar questions where user's have not handled the (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error delegate to dismiss the composer on cancel. I have handled that as well but I cant seem to figure out for the life of me why the action sheet wont show up in the visible area of the screen in the iPhone version of my universal app. The view frame of the viewcontroller modally presenting the mail composer as NSLogged is (0,0,320,480). My app is universal & the mail composer works perfectly on the iPad. Below is a screenshot of how the composer view looks, running on iPhone Simulator 5.1:-

enter image description here
Here's the code to display the composer:

-(IBAction)mailButtonPressed:(id)sender {

    MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
    controller.mailComposeDelegate = self;
    [controller setSubject:@"Subject"];
    [controller setMessageBody:@"Test" isHTML:YES];
    [controller setToRecipients:nil];

    if(controller) {
        [self presentModalViewController:controller animated:YES];
        [controller release];
    }
}

- (void)mailComposeController:(MFMailComposeViewController*)controller 
          didFinishWithResult:(MFMailComposeResult)result
                        error:(NSError*)error 
{ 
    [self dismissModalViewControllerAnimated:YES];
}
Erroneous answered 13/12, 2012 at 18:52 Comment(31)
can you post the code for how you are presenting the mail composer?Camerlengo
I've edited the question with added codeErroneous
Please also post code for didFinishWithResult delegate methodMcsweeney
Try printing out the error: NSLog(@"Error: %@", error);Camerlengo
The delegate does not get triggered for that to be done! Presumably because of the Save/Discard draft action sheet that normally shows up.Erroneous
Ok try commenting out the controller release line.. want to see if maybe its getting dealloced before dismissingCamerlengo
I did try that but to no avail :(Erroneous
Very weird.. I am guessing it has something to do with you having a universal app and having something wrong in your setup... But I just can't really know much else without diving in to your project.I would try to maybe do the same approach somewhere else in your app or in a new app altogether to see if you can get different resultsCamerlengo
I did try with a different view. The one presenting the mail composer is one of several views. Trying to display the mail composer in other views works correctly. I tried deleting and recreating the 'issue' view controller but had no change in results.Erroneous
the view controller handling the mailButtonPressed method, is it inside a navigation controller?Drank
Wow... You counter my moves every time! I am pretty stumped now.. Is there anything different about the problem view controller than the other ones. Things like: Is the problem vc presented modally when the others aren't, Is it part of a navigation stack and the others aren't. Something has to be different with that vc then the othersCamerlengo
@calvinBhai : No its only a view controller.Erroneous
@Eric: I know i do. Cuz i've fought tooth and nail with this issue and seem to be losing having tried almost everything possible! I've even gone to the extent of replacing the contents of other views with the problem one with the exception of adding the mail composer code and still nothing solves!Erroneous
does your viewcontroller conform to MFMailComposeViewControllerDelegate?Drank
Yeah it does conform. Basically, i've setup the mail composer in what would be considered the 'ideal' way to say the least.Erroneous
Trigger the problem, then pause in the debugger. Run this debugger command: po [[UIApp keyWindow] recursiveDescription]. Copy the output and paste it into your question.Snailfish
I tried this on iOS5.1 and on iOS 6.0. I have not been able to get the delegate to execute no matter what I try, whether or not the "discard draft" message ever appears. It's as though the documentation for the delegate method is wrong. I don't think the problem is the "discard draft" being offscreen, I think it's the delegate not being called.Effectuate
@robmayoff the problem is the debugger doesnt pause ever :(Erroneous
@Effectuate the only reasonable explaination i find for the view the UI looks is the action sheet coming up but not being visible. Can you shed light on ur scenario to get the same problem ? :(Erroneous
I agree your version looks like the action sheet appearing offscreen. However, I don't see that dimming on either iPhone (3GS or 4) I tried it on. I do see the "discard draft" action sheet when there is an unsent, edited draft to be discarded. But the delegate is never called. ` MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc]init]; mailer.delegate = self; [self presentModalViewController:mailer animated:true];`Effectuate
You were right to be suspicious. I wrote mailer.delegate = self; instead of mailer.mailComposeDelegate = self; and did indeed have the wrong delegate definition. Now the code behaves perfectly normally on both these iPhones. No dimmed views; everything dismisses as expected. I started trying with an iPhone app, and that was normal. I switched it to a universal app running on iPhones, and that was normal too.Effectuate
I think there's something wrong with the UIWindow. how do you set it up? You should create it in application:didFinishLaunchingWithOptions: with self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];Macario
thats precisely the same way its setup. an nslog of the frame prints {{0, 0}, {320, 480}}Erroneous
OK, none of us has any idea, and I tried to reproduce it and failed miserably. How about sharing the entire xcode project and letting us run it and see if we get the same result? Github? And, by the way, Happy Christmas!Effectuate
can you paste code of didFinishLaunchingWithOptions function of AppDelegate class..Misappropriate
I have one trick, instead of [self presentModalViewController:controller animated:YES];, use rootviewcontroller class of appDelegate, by making instance of your AppDelegate [[UIApplication sharedApplication] delegate], in your current class and then just replacing self with appDelegate.(your rootviewController class). Let me know if this solves your issue.Misappropriate
Why doesn't your debugger pause? You should be able to run Product->Debug->Pause (or click pause button on the debugger bar) before/after clicking Cancel button and run the code rob mayoff mentioned. It can help you find out if there are any views outside of the screen.Accelerant
Did you make category to override UIActionSheet method? Is there any chance your code thinks the device is iPad and try to pop the action sheet even when it is an iPhone?Gardel
AFAIK, on the iPad the actionsheet comes up as a 'popover' and not an action sheet.Erroneous
@Kevin did you find the solution? I am facing the same problem.Beera
@AnatolyAnatoly I had this pur aside for a while before I revisited it. Ended up displaying the mail composer via the rootviewcontroller rather than the current view controller. HTH.Erroneous
S
5

Why not try removing the code, and retrying while following a tutorial online such as this one:

http://iphonedevsdk.com/forum/tutorial-discussion/43633-quick-tutorial-on-how-to-add-mfmailcomposeviewcontroller.html

In cases like these, you always forget the one simple line of code needed to work so following a tutorial helps me make sure all the code necessary is there.

Try this code instead:

- (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];
}
Solanaceous answered 25/12, 2012 at 14:1 Comment(2)
I have :) with the issue being annoying i've kept a microscopic eye to not miss out on something trivial :)Erroneous
Use "controller" instead of "self". Otherwise it won't work.Kingly
C
2

Use this whole code here for the message:

.h

    #import <MessageUI/MFMailComposeViewController.h>
    @interface EmailViewController : UIViewController<MFMailComposeViewControllerDelegate>

.m

  -(IBAction)Email {

        MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
            [composer setMailComposeDelegate:self];
            if ([MFMailComposeViewController canSendMail]) {
                [composer setToRecipients:[NSArray arrayWithObjects:@"[email protected]", nil]];
                [composer setSubject:@"Idea for Basic Calculator"];
                [composer setMessageBody:@"My idea is:" isHTML:NO];
                [composer setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
                [self presentModalViewController:composer animated:YES];

    }

-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
    if (error) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error with message" message:[NSString stringWithFormat:@"Error %@", [error description]] delegate:nil cancelButtonTitle:@"Try Again Later!" otherButtonTitles:nil, nil];
        [alert show];
        [self dismissModalViewControllerAnimated:YES];
    }
    else {
        [self dismissModalViewControllerAnimated:YES];
    }
}
Coccidioidomycosis answered 28/12, 2012 at 13:24 Comment(1)
thanks, but the problem in essence isn't the code because as i've mentioned in the string of comments to my question, the code posted in the question works perfectly in other views.Erroneous
W
2

It is possible that the device you are trying is not able to send mail for some reason

You can check this with [MFMailComposeViewController canSendMail]

Weber answered 28/12, 2012 at 14:26 Comment(0)
F
0

Apply this in

-(void)displayComposerSheet

if(composer != nil) {

    [composer release];

    composer = nil;

}

After giving value to this object

[picker composer];
Flushing answered 29/12, 2012 at 12:36 Comment(0)
P
0

Looks like you are not using Automatic Reference counting (ARC). You are releasing the mail compose controller too early. Release it after it's dismissed.

Remove this line: [controller release]

if(controller) {
    [self presentModalViewController:controller animated:YES];
    /// remove this: ---->  [controller release];
}

and release this controller here

- (void)mailComposeController:(MFMailComposeViewController*)controller 
          didFinishWithResult:(MFMailComposeResult)result
                        error:(NSError*)error 
{ 
    [self dismissModalViewControllerAnimated:YES];

    [controller release]; // <----     add this
}
Prang answered 29/12, 2012 at 21:6 Comment(0)
M
0

Add this to your (all) UIViewControllers to check whether your iPhone runs out or memory. That could explain the weird behaviour i.e. mailComposerSheet released your base viewController, so the mailComposerDelegate is nil.

- (void)didReceiveMemoryWarning
{
  NSLog(@"didReceiveMemoryWarning");
  [super didReceiveMemoryWarning];
}
Misapprehension answered 30/12, 2012 at 0:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.