16

I'm trying to implement MFMailComposeViewController in case of sending the emails from within my application. The problem is that after presenting MFMailComposeViewController it is not dismissing by "Cancel" or "Send" buttons, just a bit scrolls up.

Here is the presenting of it:

func mailButtonDidPressed {
        let emailTitle = "Test email"
        let messageBody = "some body bla bla bla"
        let toRecipents = "email@gmail.com"

        let emailComposer = MFMailComposeViewController()
        emailComposer.setSubject(emailTitle)
        emailComposer.setMessageBody(messageBody, isHTML: false)
        emailComposer.setToRecipients([toRecipents])
        emailComposer.mailComposeDelegate = self
        self.presentViewController(emailComposer, animated: true, completion: nil)
    }

and dismissing delegate code:

func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
    switch (result) {
    case MFMailComposeResultSent:
        print("You sent the email.")
        break
    case MFMailComposeResultSaved:
        print("You saved a draft of this email")
        break
    case MFMailComposeResultCancelled:
        print("You cancelled sending this email.")
        break
    case MFMailComposeResultFailed:
        print("Mail failed:  An error occurred when trying to compose this email")
        break
    default:
        print("An error occurred when trying to compose this email")
        break
    }

    controller.dismissViewControllerAnimated(true, completion: nil)
}

I have surfed through the StackOverflow and other services like this and could not find any answer.

Pavel Zagorskyy
  • 443
  • 1
  • 4
  • 20

7 Answers7

12

Swift 5

Remember to add both delegates:

emailComposer.mailComposeDelegate = self
emailComposer.delegate = self

If you only add one, it won't dismiss. Also make sure to implement the delegate method:

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    dismiss(animated: true)
}
Ken Mueller
  • 3,659
  • 3
  • 21
  • 33
9

If anybody's having this problem in Swift 3.0, I think there might be two methods for MFMailComposeViewController that look similar to the CORRECT method.

Make sure you are using this method

  func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true, completion: nil)
    }
Terry Bu
  • 889
  • 1
  • 14
  • 31
6

for swift 3 you have to add

        composer.mailComposeDelegate = self as MFMailComposeViewControllerDelegate
M.Ali El-Sayed
  • 1,608
  • 20
  • 23
5

I solved writing in this way removing the completion in this way:

extension UIViewController: MFMailComposeViewControllerDelegate {

    func sendEmail() {
      //send email
    }

    public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true)
    }

}
cyclingIsBetter
  • 17,447
  • 50
  • 156
  • 241
0

Assuming mailComposeControllermailComposeControlleris a function of the same class as mailButtonDidPressedmailButtonDidPressed, it should be its instance that dismiss the MFMailComposeViewController, so

self.dismissViewControllerAnimated(true, completion: nil)

instead of

controller.dismissViewControllerAnimated(true, completion: nil)

SeNeO
  • 417
  • 2
  • 9
0

You didn't add the delegate :

emailComposer.delegate = self 

your code should be like this :

func mailButtonDidPressed {
        ...

        let emailComposer = MFMailComposeViewController()
       emailComposer.delegate = self 

...
    }
Chlebta
  • 3,090
  • 15
  • 50
  • 99
  • 3
    `emailComposer.mailComposeDelegate = self` I can see this in OPs code. – GoodSp33d Aug 09 '16 at 13:25
  • I'm not sure 100% but it's not the same – Chlebta Aug 09 '16 at 13:26
  • 1
    emailComposer.delegate = self this delegate should conform UINavigationControllerDelegate, are sure that I should conform to that protocol in my view controller? – Pavel Zagorskyy Aug 09 '16 at 13:27
  • Please can you add debug point at `controller.dismissViewControllerAnimated(true, completion: nil)` and show me what you got in debugger ? – Chlebta Aug 09 '16 at 13:31
  • 2016-08-09 16:32:01.806 MyProject[2899:1110844] Presenting view controllers on detached view controllers is discouraged < MyProject.ViewController: 0x13096a470>. You cancelled sending this email. – Pavel Zagorskyy Aug 09 '16 at 13:32
  • are you using swift 2 or 3 ? – Chlebta Aug 09 '16 at 13:36
  • 1
    @user3224534 It looks like you are presenting view controller from the child view controller. can you try [presenting from parent](http://stackoverflow.com/questions/19890761/warning-presenting-view-controllers-on-detached-view-controllers-is-discourage) ? – GoodSp33d Aug 09 '16 at 13:44
  • double checked what I've done, after GoodSp33d hint, there was a problem with my navigation flow, thank you, problem solved – Pavel Zagorskyy Aug 09 '16 at 16:02
0

I had this problem and the answer was extremely simple. Make sure to include

MFMailComposeViewControllerDelegate

in the top as when you are listing your inheritances, and then include the stuff from the other answers.

Link1600
  • 1
  • 2