3

I have a some kind of action sheet UIView which calls MFMailComposeViewController after tapping a button in it, the MFMailComposeViewController gets called and presented successfully, but it doesn't dismiss when the I tap Cancel and sometimes crashes, I know this is a known problem, but I have tried all the known fixes but it doesn't work for me. That's my code:

SendFeedback.h:

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

@interface SendFeedback : UIView <UITableViewDelegate, UITableViewDataSource, MFMailComposeViewControllerDelegate, UINavigationControllerDelegate>

//Useless code to the problem.    

@property (nonatomic, retain) MFMailComposeViewController *feedBackComposer;

@end

SendFeedback.m:

- (void)baseInit
{
    //Useless code to the problem. 

    feedBackComposer = [[MFMailComposeViewController alloc] init];
    [feedBackComposer setMailComposeDelegate:self];
    [feedBackComposer setToRecipients:[NSArray arrayWithObject:@"info@getibox.com"]];
    [feedBackComposer setMessageBody:@"" isHTML:NO];
    [feedBackComposer setSubject:@"What I Love About iBox"];
}

And to call the composer: - (void)sendFeedbackComposer { [self.window.rootViewController presentViewController:feedBackComposer animated:YES completion:nil]; }

To dismiss it:

- (void)mailComposeController:(MFMailComposeViewController *)feedBackComposer didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
    //This method doesn't get called.

    [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];

    NSLog(@"Error: %@", error);
}

EDIT: So, all the answers provided in this question were correct, and it was all my bad. What I wanted to do is: I had a UINavigationController which includes a UITableView one of the cells in that view should trigger an action sheet which is a UITableView by adding it as a subview, just like the previous one, this view also includes cells and one of them will do an action and it is calling an MFMailComposeViewController, which gets called but doesn't dismiss successfully even though I had its delegate set up and all the methods correct, the cause of the problem was the way of calling the MFMailComposeController, I first removed from super view that little UITableView then presented the MFMailComposeController, so when I dismissed the mail composer it crashed without even giving a result, which made me confuse the cause of the crash with the delegate method, fool me. Here's the code:

- (void)removeView
{
    if (self) {
        [UIView animateWithDuration:0.3
                         animations:^{backgroundView.alpha = 0;}
                         completion:^(BOOL finished){

        [UIView animateWithDuration:.3
                         animations:^{self.frame = CGRectMake(0, 568, 320, 568);}
                         completion:^(BOOL finished){[self removeFromSuperview];}];
        }];
    }
}
- (void)sendFeedbackComposer
{
    feedBackComposer = [[MFMailComposeViewController alloc] init];
    [feedBackComposer setMailComposeDelegate:self];
    [feedBackComposer setToRecipients:[NSArray arrayWithObject:@"info@getibox.com"]];
    [feedBackComposer setMessageBody:@"" isHTML:NO];
    [feedBackComposer setSubject:@"What I Love About iBox"];

    [self.window.rootViewController presentViewController:self.feedBackComposer animated:YES completion:nil];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    switch (indexPath.row) {
        case 2: //That's the index of the MailComposer caller.
            [self removeView];
            [self sendFeedbackComposer];
            break;
        case 6:
            [self removeView];
            break;
        default:
            break;
    }
}
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
    [feedBackComposer.presentingViewController dismissViewControllerAnimated:YES completion:nil];

    NSLog(@"Error: %@", error);
}

Thanks to Stefan Atanasov, Jim, and Vitaly S.

Abdelrahman Eid
  • 881
  • 2
  • 13
  • 28

4 Answers4

3

Are you sure that delegate method isn't called? I made a test and it's called, but to dismiss mail composer use such code:

[feedBackComposer dismissViewControllerAnimated: YES completion: nil];

Also it's really strange to implement delegates in view implementation, not in view controller

Vitaly S.
  • 2,389
  • 26
  • 40
  • Yes, it works in `UIViewController` but it doesn't in a `UIView`, I don't know why, I used your code and it gives the same results. I will explain what I'm trying to achieve: I have a `UIViewController` which contains a button that adds that `UIView` as a subview, it's like an action sheet, then one of the buttons in that `UIView` should call the `MFMailComposeViewController`, that's why I'm trying to do it from a `UIView` not a `UIViewController`, any other suggestions about that are appreciated. – Abdelrahman Eid Jan 25 '14 at 15:31
2

To add something to Vitaly S.'s answer (due to lack of reputation I can't comment directly on it, sorry) - the delegate method is called, so the problem is the dismissal. You can try this:

[feedBackComposer.presentingViewController dismissViewControllerAnimated: YES completion: nil];
  • 1
    But the problem isn't the dismissal, it's the method itself; it doesn't get called, not sure if it's because it's a `Subclass UIView` or what, but it's strange that other delegate methods like `UITableViewDelegate` gets called and used easily. – Abdelrahman Eid Jan 25 '14 at 15:45
  • Hm, strange - I made a simple test project with your code - the delegate method is called the first time, the composer is not dismissed and after that it's never called again (but still it's called once). – Stefan Atanasov Jan 25 '14 at 15:48
  • Strange, but how come the method got called but the composer wasn't dismissed? For me, it never gets called, and sometimes it does nothing when I tap Cancel and other times it crashes. – Abdelrahman Eid Jan 25 '14 at 15:52
  • To be honest I have no idea - this is the test project, it's basically your code, so maybe there's a problem elsewhere https://github.com/StefanAtanasov/MailComposerTest – Stefan Atanasov Jan 25 '14 at 16:05
  • Your code works! I don't what I have done wrong, I'll investigate on that now and inform you. – Abdelrahman Eid Jan 25 '14 at 16:19
  • It was all my bad, I did something that made all this go wrong, just edit your answer and add your comment to it for me to accept the answer, I will explain what I have done now. Thank you! – Abdelrahman Eid Jan 25 '14 at 16:50
1

The delegate methods need to be called from the viewController, not from within the UIView.

Your view controller that calls the UIView will have your delegates

<UITableViewDelegate, UITableViewDataSource, MFMailComposeViewControllerDelegate, UINavigationControllerDelegate>

within it's header file.

You need to make a delegate method to pass information from the UIView to the controller, which will in turn call the mail and table delegate methods.

Here is a link to a question that demonstrates how to use a delegate protocol to trigger a method in the view controller from the UIView.

Trigger a method in UIViewController from its View

Hope this helps, Jim

Community
  • 1
  • 1
Jim Tierney
  • 4,078
  • 3
  • 27
  • 48
  • Oh, I guessed that too! But how come `` gets called and used successfully? Besides, this `UIView` is a `subclass`, not the `UIView` of the `UIViewController` can I still trigger the method in the `UIViewController`? And thanks for your answer. – Abdelrahman Eid Jan 25 '14 at 15:24
0

you need to check is it device is configure to send mail by checking MFMailComposeViewController is avail to respond or not.

  if([MFMailComposeViewController canSendMail]){
  //your code
  }
Prad
  • 51
  • 2