MFMailComposeViewController view does not dismiss 2nd time - ios

I have what I believe is a unique problem. I am having trouble getting my email window to dismiss. I am using Xcode 8.
The email dismisses correctly the first time I open it, but if I open it again it won't. If I press "Cancel" it does not give me the option to "Delete Draft". If I press "Send" the email is sent, but the window does not dismiss.
My code is below. The mailComposeController gets called correctly the first time, but it never gets called a second time. Does anyone have any ideas about what I am missing?
let mail = MFMailComposeViewController()
func sendEmail(body: String, subject: String) {
if MFMailComposeViewController.canSendMail() {
mail.mailComposeDelegate = self
mail.setSubject(subject)
mail.setMessageBody("\(body)", isHTML: false)
if let data = (body as NSString).data(using: String.Encoding.utf8.rawValue){
//Attach File
mail.addAttachmentData(data, mimeType: "text/plain", fileName: "data.txt")
}
present(mail, animated: true)
} else {
// show failure alert
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true, completion: nil)
}

You need to create a new MFMailComposeViewController each time. Moving your mail declaration inside sendEmail works…
func sendEmail(body: String, subject: String) {
if MFMailComposeViewController.canSendMail() {
// Create a new MFMailComposeViewController…
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setSubject(subject)
mail.setMessageBody("\(body)", isHTML: false)
if let data = (body as NSString).data(using: String.Encoding.utf8.rawValue){
//Attach File
mail.addAttachmentData(data, mimeType: "text/plain", fileName: "data.txt")
}
present(mail, animated: true)
} else {
// show failure alert
}
}
As to why…?

Related

Refer a friend through sms getting White screen

Hi I am writing the following code to refer a friend through SMS.
When I click on cell, the sms app opens with text but when again I tried for second time, it shows white color screen.
Here is my code
var controller1 = MFMessageComposeViewController()
extension ReferaFriendController:UICollectionViewDelegate,UICollectionViewDataSource,MFMessageComposeViewControllerDelegate
{
if indexPath.item == 0
{
if MFMessageComposeViewController.canSendText() {
let urlToShare = self.referalmodeldata[0].referralCodeOnly
controller1.body = "Hey I just gave an Awesome Assessment on App you can also try it. I scored , Try to beat my score \(String(describing: urlToShare))"
controller1.messageComposeDelegate = self
self.present(controller1, animated: true, completion: nil)
}
}
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
self.dismiss(animated: true, completion: nil)
}
}
As far as I can see, there's no need to keep a reference to the MFMessageComposeViewController. Just move it to be created at the point you need it, inside your if closure:
if MFMessageComposeViewController.canSendText() {
let controller = MFMessageComposeViewController()
// ...
}

open "Messages" app in my app

I'm trying to develop an app, that take a number from a variable then open in "Messages" app with (1500) in the field To: and the variable value in Text Messages field like this
I tried this answer how to open an URL in Swift3 and Swift: How to open a new app when uibutton is tapped but i didn't figure out the URL for Messages app
what should I use? Big thanks.
use this
if MFMessageComposeViewController.canSendText() == true{
let recipients:[String] = ["1500"]
var messageController = MFMessageComposeViewController()
//messageController.messageComposeDelegate = self // implement delegate if you want
messageController.recipients = recipients
messageController.body = "Your_text"
self.present(messageController, animated: true, completion: nil)
}
You need to import "MessageUI" to your class and use the below code.
func sendMessages() {
if MFMessageComposeViewController.canSendText() == true {
let recipients:[String] = ["9895249619"]
let messageController = MFMessageComposeViewController()
messageController.messageComposeDelegate = self
messageController.recipients = recipients
messageController.body = "Your_message_text"
self.present(messageController, animated: true, completion: nil)
} else {
//handle text messaging not available
}
}
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
controller.dismiss(animated: true, completion: nil)
}

Application tried to present a nil modal view controller on target when sending text

I'm trying to sent a text message and have controller set up like so, but I get an error message 'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target <Ally.TextMessageController: 0x7fd5361278e0>.' I've made sure that in my storyboard I'm connecting it to TextMessageController so I'm not quite sure what is causing the crash.
class TextMessageController: UIViewController, MFMessageComposeViewControllerDelegate {
var phone: String?
override func viewDidLoad() {
super.viewDidLoad()
print(phone)
var messageVC = MFMessageComposeViewController()
messageVC.body = "Hey I need help, are you available";
messageVC.recipients = ["555555555"]
messageVC.messageComposeDelegate = self;
presentViewController(messageVC, animated: false, completion: nil)
// Do any additional setup after loading the view.
}
func canSendText() -> Bool {
return MFMessageComposeViewController.canSendText()
}
func messageComposeViewController(controller: MFMessageComposeViewController!, didFinishWithResult result: MessageComposeResult) {
self.dismissViewControllerAnimated(true, completion: nil)
switch (result.rawValue) {
case MessageComposeResultCancelled.rawValue:
print("Message was cancelled")
self.dismissViewControllerAnimated(true, completion: nil)
case MessageComposeResultFailed.rawValue:
print("Message failed")
self.dismissViewControllerAnimated(true, completion: nil)
case MessageComposeResultSent.rawValue:
print("Message was sent")
self.dismissViewControllerAnimated(true, completion: nil)
default:
break;
}
}
Here is the error message
'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target <Ally.TextMessageController: 0x7fd5361278e0>.'
You should first check whether device can send the text message and then only present it. For instance simulator can not send text message thus your code will crash in it. Along with simulator, user’s device may not be set up for the delivery of messages. So perform following check
if messageVC.canSendText() {
presentViewController(messageVC, animated: false, completion: nil)
}

MFMailComposeViewController not responding or populating

This is a Swift 2.0 project. I have a MFMailComposeViewController that appears as expected, but does not populate the contents, and does not respond to user interaction, except for the Cancel button, which dismisses it.
The send button is greyed out. None of the text fields respond to user touch.
Running on an iPhone 6+ iOS 8.4.1, Xcode 7.0b6
What am I missing?
Here is the code I'm using:
#IBAction func hitSendEmail(sender: AnyObject) {
let emailTitle = "Title goes here"
let emailBody = "Blah blah blah blah."
let recipientAddress = "EMAILGOESHERE"
mailViewController = MFMailComposeViewController()
guard let mailvc = mailViewController else {
return
}
mailvc.mailComposeDelegate = self
mailvc.setSubject(emailTitle)
mailvc.setMessageBody(emailBody, isHTML: false)
mailvc.setToRecipients([recipientAddress])
self.presentViewController(mailvc, animated: true) { () -> Void in
}
}
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
if let vc = controller.presentingViewController {
vc.dismissViewControllerAnimated(true, completion: { () -> Void in
self.mailViewController = nil
})
}
}
SOLVED: Apparently it's a bug in Xcode 7.0b6.
I recompiled the app under Xcode 6.4 (after changing the 'guard' statement to an 'if let') and it runs without problem.

Failed on using Swift to implement in-app email

I want to use swift to implement in-app email. When I click the button, the email window pops up. However, I am unable to send my email. Moreover, after I click cancel-delete draft, I cannot go back to the original screen.
import UIkit
import MessageUI
class Information : UIViewController, MFMailComposeViewControllerDelegate{
var myMail: MFMailComposeViewController!
#IBAction func sendReport(sender : AnyObject) {
if(MFMailComposeViewController.canSendMail()){
myMail = MFMailComposeViewController()
//myMail.mailComposeDelegate
// set the subject
myMail.setSubject("My report")
//To recipients
var toRecipients = ["lipeilin#gatech.edu"]
myMail.setToRecipients(toRecipients)
//CC recipients
var ccRecipients = ["tzhang85#gatech.edu"]
myMail.setCcRecipients(ccRecipients)
//CC recipients
var bccRecipients = ["tzhang85#gatech.edu"]
myMail.setBccRecipients(ccRecipients)
//Add some text to the message body
var sentfrom = "Email sent from my app"
myMail.setMessageBody(sentfrom, isHTML: true)
//Include an attachment
var image = UIImage(named: "Gimme.png")
var imageData = UIImageJPEGRepresentation(image, 1.0)
myMail.addAttachmentData(imageData, mimeType: "image/jped", fileName: "image")
//Display the view controller
self.presentViewController(myMail, animated: true, completion: nil)
}
else{
var alert = UIAlertController(title: "Alert", message: "Your device cannot send emails", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
func mailComposeController(controller: MFMailComposeViewController!,
didFinishWithResult result: MFMailComposeResult,
error: NSError!){
switch(result.value){
case MFMailComposeResultSent.value:
println("Email sent")
default:
println("Whoops")
}
self.dismissViewControllerAnimated(true, completion: nil)
}
}
Since you haven't set the current view controller as the mailComposeDelegate of myMail, the mailComposeController:didFinishWithResult method isn't being called. After you init myMail, make sure to add:
myMail.mailComposeDelegate = self
and you'll be good to go
In case anyone is looking for a non MFMailCompose option, here's what I did to send using Gmail's SMTP servers.
Download a zip of this repo: https://github.com/jetseven/skpsmtpmessage
Drag and drop the files under SMTPLibrary into your XCode project
Create a new header file - MyApp-Briding-Header.h
Replace new header file with this:
#import "Base64Transcoder.h"
#import "HSK_CFUtilities.h"
#import "NSData+Base64Additions.h"
#import "NSStream+SKPSMTPExtensions.h"
#import "SKPSMTPMessage.h"
Go to Project(Targets > MyApp on the left)/Build Settings/Swift Compiler - Code Generation
Add path to header file under Objective-C Briding Header -> Debug (i.e. MyApp/MyApp-Bridging-Header.h
Go to Project/Build Phases/Compile Sources
Select all .m files and click enter. Type -fno-objc-arc and hit enter.
Use this code to send email:
var mail = SKPSMTPMessage()
mail.fromEmail = "fromemail#gmail.com"
mail.toEmail = "tomail#gmail.com"
mail.requiresAuth = true
mail.login = "fromemail#gmail.com"
mail.pass = "password"
mail.subject = "test subject"
mail.wantsSecure = true
mail.relayHost = "smtp.gmail.com"
mail.relayPorts = [587]
var parts: NSDictionary = [
"kSKPSMTPPartContentTypeKey": "text/plain; charset=UTF-8",
"kSKPSMTPPartMessageKey": "test message",
]
mail.parts = [parts]
mail.send()
Hope it helps someone. I didn't want to use the MFMailCompose option because I didn't want to have to prompt the user.
This is how I have composed my email with attached PDF file document.
Just to test this example you need to drag and drop a sample PDF named "All_about_tax.pdf"
#IBAction func sendEmail(sender: UIButton)
{
//Check to see the device can send email.
if( MFMailComposeViewController.canSendMail() )
{
print("Can send email.")
let mailComposer = MFMailComposeViewController()
mailComposer.mailComposeDelegate = self
//Set to recipients
mailComposer.setToRecipients(["your email id here"])
//Set the subject
mailComposer.setSubject("Tax info document pdf")
//set mail body
mailComposer.setMessageBody("This is what they sound like.", isHTML: true)
if let filePath = NSBundle.mainBundle().pathForResource("All_about_tax", ofType: "pdf")
{
print("File path loaded.")
if let fileData = NSData(contentsOfFile: filePath)
{
print("File data loaded.")
mailComposer.addAttachmentData(fileData, mimeType: "application/pdf", fileName: "All_about_tax.pdf")
}
}
//this will compose and present mail to user
self.presentViewController(mailComposer, animated: true, completion: nil)
}
else
{
print("email is not supported")
}
}
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?)
{
self.dismissViewControllerAnimated(true, completion: nil)
}

Resources