1

I tried to use MailComposer. Here is the code I used:

func setupMailer() {
    if MFMailComposeViewController.canSendMail() {
        emailController.mailComposeDelegate = self
        emailController.setToRecipients([]) // set the email address
        emailController.setSubject("BackgroundTask Test")
        emailController.setMessageBody("Message body", isHTML: false)
    }
}

And then when user presses a button:

func buttonPressed(button: UIButton) {
    debugPrint("buttonPressed", button)
    let path = dirpath.appendingPathComponent(filename)
    let data = NSData(contentsOfFile: path.path)
    emailController.mailComposeDelegate = self
    emailController.addAttachmentData(data! as Data, mimeType: "text/csv", fileName: filename)
    present(emailController, animated: true, completion: nil)
}

And when dismiss:

@objc func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    debugPrint("mailComposeController dismiss")
    controller.dismiss(animated: true, completion: nil)
}

It is found that if the button is pressed for the first time, the mail composer works normally no matter I choose send or cancel.

However, after I send/cancel, for the 2nd time onwards, the mail composer cannot be dismissed. The send has response that can send the email, but the mail composer interface never dismiss.

I found that the function func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) is not triggered any more after the first time.

Any clues?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
user6539552
  • 1,331
  • 2
  • 19
  • 39

3 Answers3

2

You are not supposed to use the same MFMailComposeViewController instance again..

Try this

func setupMailer() {
    if MFMailComposeViewController.canSendMail() {
        emailController = MFMailComposeViewController.init()
        emailController.mailComposeDelegate = self
        emailController.setToRecipients([]) // set the email address
        emailController.setSubject("BackgroundTask Test")
        emailController.setMessageBody("Message body", isHTML: false)
    }
}
Bilal
  • 18,478
  • 8
  • 57
  • 72
  • Great, I didn't know that I can't reuse same instance of MFMailComposeViewController - every time if you want present mail composer you must create a NEW instance. – MarcinR Dec 01 '19 at 15:41
2

Well don't know what you're doing wrong. I think you're using Swift. So I will explain you how can you implement that. Steps:

1) import MessagesUI and add delegate MFMailComposeViewControllerDelegate

2) Add this function:

func configuredMailComposeViewController() -> MFMailComposeViewController {
    let mailComposerVC = MFMailComposeViewController()
    mailComposerVC.mailComposeDelegate = self
    mailComposerVC.setToRecipients(["someone@somewhere.com"])
    mailComposerVC.setSubject("Sending you an in-app e-mail...")
    mailComposerVC.setMessageBody("Sending e-mail in-app is not so bad!", isHTML: false)

    return mailComposerVC
}

3) Call the above function in IBAction of button as:

let mailComposeViewController = configuredMailComposeViewController()
    if MFMailComposeViewController.canSendMail() {
        self.present(mailComposeViewController, animated: true, completion: nil)
    } else {
        // Show alert if user can't send mail
    }

4) Lastly implement delegate method:

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    controller.dismiss(animated: true, completion: nil)
}
Anmol
  • 77
  • 1
  • 10
1

Right, the point is that I reuse the emailController instance.

  func setupMailer() {
if MFMailComposeViewController.canSendMail() {
  emailController = MFMailComposeViewController()
  emailController.mailComposeDelegate = self
  emailController.setToRecipients([]) // set the email address
  emailController.setSubject("BackgroundTask Test")
  emailController.setMessageBody("Message body", isHTML: false)
}

}

  func buttonPressed(button: UIButton) {
    debugPrint("buttonPressed", button)
    let path = dirpath.appendingPathComponent(filename)
    let data = NSData(contentsOfFile: path.path)
    setupMailer()
    emailController.addAttachmentData(data! as Data, mimeType: "text/csv", fileName: filename)
    present(emailController, animated: true, completion: nil)
  }

  @objc func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    debugPrint("mailComposeController dismiss")
    controller.dismiss(animated: true, completion: nil)
  }

This works now.

Billal Begueradj
  • 20,717
  • 43
  • 112
  • 130
user6539552
  • 1,331
  • 2
  • 19
  • 39