Do I have to dismiss a MFMessageComposeViewController in its didFinishWithResult delegate method? - ios

I'm trying to allow the user to send multiple text messages in succession in a MFMessageComposeViewController, but if I don't dismiss the controller in the didFinishWithResult delegate method, the Cancel button in the top right corner becomes disabled, and the user has no way of getting out of the text message interface.
Is the MFMessageComposeViewController only for sending one-off messages?
func messageComposeViewController(controller: MFMessageComposeViewController!, didFinishWithResult result: MessageComposeResult) {
if result.value == MessageComposeResultCancelled.value {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
Thanks for the help.

Related

How to get recipients list from MFMailComposeViewController in delegate didFinishWith method

I'm trying to implement the feature where user can invite friends on App via Messages and Email.
I am using MFMessageComposeViewController for message and MFMailComposeViewController for email.
For messages in delegate method
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
if result == .sent {
updateAndStoreInvitation(controller.recipients)
}
dismiss(animated: true)
}
we get the recipients and store them to show that this user already invited.
but for email case
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
if result == .sent {
}
dismiss(animated: true)
}
does not provide recipients list.
is there any way to get recipients list in MFMailComposeViewController in delegate method on result == .sent

How can I avoid an 1100 error using MFMailComposeViewControllerDelegate?

I'm trying to send an email from with my Swift app. Nothing fancy. Subject. Body. Recipients. I'm doing this like the examples I've seen which is to say NOT using a separate view controller - just a basic vc but specifying MFMailComposeViewControllerDelegate like so:
class MyVC: UIViewController, MFMailComposeViewControllerDelegate
I then have the two methods I see in all the examples:
#IBAction func sendEmail()
{
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setSubject(subject)
mail.setToRecipients(recipients)
mail.setMessageBody(content, isHTML: true)
present(mail, animated: true)
} else {
// show failure alert
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?)
{
controller.dismiss(animated: true)
}
But when the email gets cancelled (Delete Draft) I get:
[AXRuntimeCommon] AX Lookup problem - errorCode:1100 error:Permission denied portName:'com.apple.iphone.axserver'
No crashing. Emails get sent just fine. But I noticed that the cancelled emails pile up in Mail. The drafts are not being deleted. What am I missing? Does anyone have this kind of thing working?

How to close MFMailComposeViewController?

I want to send an email from my Swift application and it works well, it sends the email.
Nevertheless, after sending the email, the layout does not quits. I want to quit the layout after sending the email. I also want this behaviour when I press on Cancel, Remove draft or Save draft button.
This is the code that I have to send the email (after pressing a button):
#IBAction func btnSendEmailAction(_ sender: AnyObject) {
let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
composeVC.setToRecipients(["mymail#mail.com"])
composeVC.setSubject("Hello!")
composeVC.setMessageBody("Hello World!", isHTML: false)
self.present(composeVC, animated: true, completion: nil)
}
func mailComposeController(controller: MFMailComposeViewController,
didFinishWithResult result: MFMailComposeResult, error: NSError?) {
switch result {
case MFMailComposeResult.cancelled:
controller.dismiss(animated: true, completion: nil)
break
case MFMailComposeResult.sent:
controller.dismiss(animated: true, completion: nil)
break
case MFMailComposeResult.failed:
controller.dismiss(animated: true, completion: nil)
break
default:
break
}
controller.dismiss(animated: true, completion: nil)
}
but the layout does not quits when I press on Cancel or Sent buttons.
I know that there are a lot of questions related about this problem but I looked a lot of them and this is the code I could get from a mix of some of them. Note that most of them are in Objective instead of Swift (and sometimes the methods does not exist).
Example: iPhone: How to Close MFMailComposeViewController?
Am I missing something on my code? How can I detect Remove draft and Save Draft events?
Thanks in advance!
Looks like you're using swift 3 and not using a valid delegate method. Corrected delegate method is this:
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
switch result {
case .cancelled:
break
case .saved:
break
case .sent:
break
case .failed:
break
}
dismiss(animated: true, completion: nil)
}

how to dismiss mail view controller after tapping send or cancel button

while sending mail, after tapping send or cancel button view controller stays there and app stalls.
//swift 2.2 ; xcode 7.3.1 ;
if( MFMailComposeViewController.canSendMail() ) {
print("Can send email.")
}
var subjectText = "Verification"
var toReceipients = ["notorious.roman#gmail.com"]
// var msgBody = "Verified"
var mc:MFMailComposeViewController = MFMailComposeViewController()
mc.mailComposeDelegate = self
mc.setSubject(subjectText)
mc.setMessageBody("Verified", isHTML: false)
mc.setToRecipients(toReceipients)
self.presentViewController(mc, animated: true, completion: nil)
}
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
self.dismissViewControllerAnimated(true, completion: nil)
}
Swift 4.0 Update.
Swift 5.0 Update.
Allow me to add something to the discussion...
In Swift 4 and 5 the delegate method slightly changed; As it's posted by you now, won't do any effect and won't get called. It happened to me, drove me crazy!
The Xcode warning suggest three fixes but first two could be misleading. It's just a tiny fix...
Here's the delegate method fixed for Swift 3, 4 and 5:
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
// Dismiss the mail compose view controller.
controller.dismiss(animated: true, completion: nil)
}
Still, Victor's answer should be the correct/accepted one.
Enjoy!
I think #rmaddy answer your question in his comment, nevertheless I going to explain you what's happening. You're trying to dismiss the UIViewController that presents the MFMailComposeViewController not the MFMailComposeViewController.
As Apple specify in his documentation:
The mail compose view controller is not dismissed automatically. When the user taps the buttons to send the email or cancel the interface, the mail compose view controller calls the mailComposeController:didFinishWithResult:error: method of its delegate. Your implementation of that method must dismiss the view controller explicitly.
So you need to set the method in this way:
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
// Dismiss the mail compose view controller.
controller.dismissViewControllerAnimated(true, completion: nil)
}
I hope this help you.
is had an Switch Statement that controls it for me:
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
switch result.rawValue {
case MFMailComposeResult.cancelled.rawValue :
print("Cancelled")
case MFMailComposeResult.failed.rawValue :
print("Failed")
case MFMailComposeResult.saved.rawValue :
print("Saved")
case MFMailComposeResult.sent.rawValue :
print("Sent")
default: break
}
self.dismiss(animated: true, completion: nil)
}

How to send email in app from UI Label (Swift 2 IOS 9)?

With manipulation of this tutorial http://www.raywenderlich.com/113772/uisearchcontroller-tutorial
I have a table view displaying people, when the cell is clicked the user is redirected to another view showing their picture and their email. I want to be able to have the user click on the email address and email them. I have researched and found similar tutorials
https://www.andrewcbancroft.com/2014/08/25/send-email-in-app-using-mfmailcomposeviewcontroller-with-swift/
The problem with the tutorial above is when test running the new code the ios simulator pops up an error and wont show the composed email (Maybe a Glitch?)and If the simulator did not give an error I dont know how to display multiple emails based on which person the user selected. Any help on solutions to this problem or any alternative will be great Thanks!!
The simulator will crash when you try to open the mail. Try it on an actual device instead.
To compose a mail do the following
Add these to your class
MFMessageComposeViewControllerDelegate and MFMailComposeViewControllerDelegate
In your didSelectRowAtIndexPath, this is the function called when you presses a row in your tableView. Do the following:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let candy = candies[indexPath.row]
var mail: MFMailComposeViewController!
// yourArray is the array that you use to populate the tableView
// .mail is the variable in the object (I´m assuming you´re using objects in your array)
let toRecipients = [candy[indexPath.row].email]
let subject = "Feedback"
let body = "<br><br><p>I have a \(UIDevice.currentDevice().modelName).<br> And iOS version \(UIDevice.currentDevice().systemVersion).<br</p>"
mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(toRecipients)
mail.setSubject(subject)
mail.setMessageBody(body, isHTML: true)
presentViewController(mail, animated: true, completion: nil)
}
The delegate methods below if you need to use them
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
dismissViewControllerAnimated(true, completion: nil)
}
func messageComposeViewController(controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult) {
switch (result.rawValue) {
case MessageComposeResultCancelled.rawValue:
self.dismissViewControllerAnimated(true, completion: nil)
case MessageComposeResultFailed.rawValue:
self.dismissViewControllerAnimated(true, completion: nil)
case MessageComposeResultSent.rawValue:
self.dismissViewControllerAnimated(true, completion: nil)
default:
break;
}
}

Resources