56 votes

J'ai un VRAI malentendu avec MFMailComposeViewController en Swift (iOS8) dans le simulateur.

Je crée un fichier CSV et j'essaie de l'envoyer par e-mail. Une fenêtre d'envoi de mail s'affiche, mais le corps du mail n'est pas rempli, et il n'y a pas de fichier attaché. L'application se bloque avec cet écran :

prntscr.com/4ikwwm

Le bouton "Annuler" ne fonctionne pas. Après quelques secondes, la console apparaît :

viewServiceDidTerminateWithError: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "The operation couldn’t be completed. (_UIViewServiceInterfaceErrorDomain error 3.)" UserInfo=0x7f8409f29b50 {Message=Service Connection Interrupted}

<MFMailComposeRemoteViewController: 0x7f8409c89470> timed out waiting for fence barrier from com.apple.MailCompositionService

Voilà mon code :

func actionSheet(actionSheet: UIActionSheet!, clickedButtonAtIndex buttonIndex: Int) {
    if buttonIndex == 0 {
        println("Export!")

        var csvString = NSMutableString()
        csvString.appendString("Date;Time;Systolic;Diastolic;Pulse")

        for tempValue in results {     //result define outside this function

            var tempDateTime = NSDate()
            tempDateTime = tempValue.datePress
            var dateFormatter = NSDateFormatter()
            dateFormatter.dateFormat = "dd-MM-yyyy"
            var tempDate = dateFormatter.stringFromDate(tempDateTime)
            dateFormatter.dateFormat = "HH:mm:ss"
            var tempTime = dateFormatter.stringFromDate(tempDateTime)

            csvString.appendString("\n\(tempDate);\(tempTime);\(tempValue.sisPress);\(tempValue.diaPress);\(tempValue.hbPress)")
        }

        let fileManager = (NSFileManager.defaultManager())
        let directorys : [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory,NSSearchPathDomainMask.AllDomainsMask, true) as? [String]

        if ((directorys) != nil) {

            let directories:[String] = directorys!;
            let dictionary = directories[0];
            let plistfile = "bpmonitor.csv"
            let plistpath = dictionary.stringByAppendingPathComponent(plistfile);

            println("\(plistpath)")

            csvString.writeToFile(plistpath, atomically: true, encoding: NSUTF8StringEncoding, error: nil)

            var testData: NSData = NSData(contentsOfFile: plistpath)

            var myMail: MFMailComposeViewController = MFMailComposeViewController()

            if(MFMailComposeViewController.canSendMail()){

                myMail = MFMailComposeViewController()
                myMail.mailComposeDelegate = self

                // set the subject
                myMail.setSubject("My report")

                //Add some text to the message body
                var sentfrom = "Mail sent from BPMonitor"
                myMail.setMessageBody(sentfrom, isHTML: true)

                myMail.addAttachmentData(testData, mimeType: "text/csv", fileName: "bpmonitor.csv")

                //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)

            }
        }
        else {
            println("File system error!")
        }
    }
}

J'essaie plutôt d'envoyer du courrier en utilisant UIActivityViewController :

let fileURL: NSURL = NSURL(fileURLWithPath: plistpath)
let actViewController = UIActivityViewController(activityItems: [fileURL], applicationActivities: nil)
self.presentViewController(actViewController, animated: true, completion: nil)

Voir à peu près le même écran pour envoyer un e-mail, qui après un certain temps de retour à l'écran précédent. Dans la console, maintenant une autre erreur :

viewServiceDidTerminateWithError: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "The operation couldn’t be completed. (_UIViewServiceInterfaceErrorDomain error 3.)" UserInfo=0x7faab3296ad0 {Message=Service Connection Interrupted}
Errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo=0x7faab3005890 {NSLocalizedDescription=query cancelled}
<MFMailComposeRemoteViewController: 0x7faab3147dc0> timed out waiting for fence barrier from com.apple.MailCompositionService

Il y avait quelque chose à propos PlugInKit .

Essayer plutôt UIActivityViewController en utilisant UIDocumentInteractionController :

let docController = UIDocumentInteractionController(URL: fileURL)
docController.delegate = self
docController.presentPreviewAnimated(true)
...

func documentInteractionControllerViewControllerForPreview(controller: UIDocumentInteractionController!) -> UIViewController! {
    return self
}

Je vois cet écran avec le contenu d'un fichier CSV :

enter image description here

J'appuie sur le bouton d'exportation en haut à droite et je vois cet écran :

enter image description here

où je choisis MAIL et pendant plusieurs secondes je vois :

enter image description here

Puis revient à l'affichage du contenu du fichier ! Dans la console, les mêmes messages que lors de l'utilisation de UIActivityViewController .

1voto

Chriss Mejía Points 85

Hé, c'est résolu avec iOS 8.3 sorti il y a 2 jours.

1voto

Sunkas Points 791

Une classe d'aide simple pour gérer le courrier en Swift. Basé sur la réponse de Joe Blow.

import UIKit
import MessageUI

public class EmailManager : NSObject, MFMailComposeViewControllerDelegate
{
    var mailComposeViewController: MFMailComposeViewController?

    public override init()
    {
        mailComposeViewController = MFMailComposeViewController()
    }

    private func cycleMailComposer()
    {
        mailComposeViewController = nil
        mailComposeViewController = MFMailComposeViewController()
    }

    public func sendMailTo(emailList:[String], subject:String, body:String, fromViewController:UIViewController)
    {
        if MFMailComposeViewController.canSendMail() {
            mailComposeViewController!.setSubject(subject)
            mailComposeViewController!.setMessageBody(body, isHTML: false)
            mailComposeViewController!.setToRecipients(emailList)
            mailComposeViewController?.mailComposeDelegate = self
            fromViewController.presentViewController(mailComposeViewController!, animated: true, completion: nil)
        }
        else {
            print("Could not open email app")
        }
    }

    public func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?)
    {
        controller.dismissViewControllerAnimated(true) { () -> Void in
            self.cycleMailComposer()
        }
    }
}

Placez comme variable d'instance dans la classe AppDelegate et appelez quand nécessaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X