我对Simulator中的Swift(iOS8)中的MFMailComposeViewController有误解 [英] I have REAL misunderstanding with MFMailComposeViewController in Swift (iOS8) in Simulator

查看:260
本文介绍了我对Simulator中的Swift(iOS8)中的MFMailComposeViewController有误解的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个csv文件并尝试通过电子邮件发送它。显示发送邮件的窗口,但不填充电子邮件正文,也没有附加文件。应用程序挂起此屏幕:

I create a csv file and try to send it by e-mail. Displays a window to send mail, but is not filled with body of the email, and no attached file. Application hangs with this screen:

< img src =https://i.stack.imgur.com/ImeUH.pngalt =prntscr.com/4ikwwm>

按钮取消不起作用。在控制台中显示几秒钟后:

button "Cancel" does not work. After a few seconds in the console appears:

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

有我的代码:

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!")
        }
    }
}

尝试使用 UIActivityViewController发送邮件

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

查看大致相同的屏幕发送电子邮件,一段时间后返回上一个屏幕。在控制台中,现在又出现了另一个错误:

See approximately the same screen to send e-mail, which after a while returning to the previous screen. In the console, now another error:

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

有一些关于 PlugInKit 。

使用 UIDocumentInteractionController尝试改为 UIActivityViewController / code>:

Trying instead UIActivityViewController using UIDocumentInteractionController:

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

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

我看到此屏幕的内容为CSV-文件: http://prntscr.com/4ilgax 我按下右上角的按钮导出并看到此屏幕< a href =http://prntscr.com/4ilguk =nofollow noreferrer> http://prntscr.com/4ilguk 我在哪里选择邮件,几秒钟后我看到 http://prntscr.com/4ilh2h 然后返回显示文件的内容!在控制台中显示与使用 UIActivityViewController 时相同的消息。

I see this screen with contents a CSV-file: http://prntscr.com/4ilgax I press button export in top-right and see this screen http://prntscr.com/4ilguk where I choose MAIL and and for several seconds I see http://prntscr.com/4ilh2h Then returns to displaying the contents of the file! In the console the same messages as when using UIActivityViewController.

推荐答案

* *重要 - 请勿使用此模拟器。 * *



即使在2016年,模拟器也不支持从应用程序发送邮件。

* * IMPORTANT - DO NOT USE THE SIMULATOR FOR THIS. * *

Even in 2016, the simulators very simply do not support sending mail from apps.

事实上,模拟器根本就没有邮件客户端。

Indeed, the simulators simply do not have mail clients.

Henri给出了总答案。你必须

Henri has given the total answer. You MUST

- 在早期阶段分配和启动MFMailComposeViewController ,并且

- 将其保存在一个静态变量中,然后,

- 只要需要,获取静态MFMailComposeViewController实例并使用它。

-- whenever it's needed, get the static MFMailComposeViewController instance and use that.

并且你几乎肯定必须在每次使用后循环全​​局MFMailComposeViewController。重新使用相同的文件

AND you will almost certainly have to cycle the global MFMailComposeViewController after each use. It is not reliable to re-use the same one.

有一个全局例程,它释放然后重新初始化单例 MFMailComposeViewController 。在完成邮件编写器之后,每次调用该全局例程。

Have a global routine which releases and then re-initializes the singleton MFMailComposeViewController. Call to that global routine, each time, after you are finished with the mail composer.

在任何单例中执行此操作。不要忘记您的应用代表当然是单身人士,所以在那里做...

Do it in any singleton. Don't forget that your app delegate is, of course, a singleton, so do it there...

@property (nonatomic, strong) MFMailComposeViewController *globalMailComposer;

-(BOOL)application:(UIApplication *)application
   didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    ........
    // part 3, our own setup
    [self cycleTheGlobalMailComposer];
    // needed due to the worst programming in the history of Apple
    .........
    }

和...

-(void)cycleTheGlobalMailComposer
    {
    // cycling GlobalMailComposer due to idiotic iOS issue
    self.globalMailComposer = nil;
    self.globalMailComposer = [[MFMailComposeViewController alloc] init];
    }

然后使用邮件,就像这样......

Then to use the mail, something like this ...

-(void)helpEmail
    {
    // APP.globalMailComposer IS READY TO USE from app launch.
    // recycle it AFTER OUR USE.

    if ( [MFMailComposeViewController canSendMail] )
        {
        [APP.globalMailComposer setToRecipients:
              [NSArray arrayWithObjects: emailAddressNSString, nil] ];
        [APP.globalMailComposer setSubject:subject];
        [APP.globalMailComposer setMessageBody:msg isHTML:NO];
        APP.globalMailComposer.mailComposeDelegate = self;
        [self presentViewController:APP.globalMailComposer
             animated:YES completion:nil];
        }
    else
        {
        [UIAlertView ok:@"Unable to mail. No email on this device?"];
        [APP cycleTheGlobalMailComposer];
        }
    }

-(void)mailComposeController:(MFMailComposeViewController *)controller
     didFinishWithResult:(MFMailComposeResult)result
     error:(NSError *)error
    {
    [controller dismissViewControllerAnimated:YES completion:^
        { [APP cycleTheGlobalMailComposer]; }
        ];
    }

{nb,修正了以下每张Michael Salamone的拼写错误。}

{nb, fixed typo per Michael Salamone below.}

为了方便起见,在你的前缀文件中有以下宏

Have the following macro in your Prefix file for convenience

#define APP ((AppDelegate *)[[UIApplication sharedApplication] delegate])

此处还有轻微问题可能会花费你天: https://stackoverflow.com/a/17120065/294884

Also here's a "minor" problem which can cost you days: https://stackoverflow.com/a/17120065/294884

仅限2016年FTR这里是发送电子邮件IN APP的基本快速代码,

Just for 2016 FTR here's the basic swift code to send an email IN APP,

class YourClass:UIViewController, MFMailComposeViewControllerDelegate
 {
    func clickedMetrieArrow()
        {
        print("click arrow!  v1")
        let e = MFMailComposeViewController()
        e.mailComposeDelegate = self
        e.setToRecipients( ["help@smhk.com"] )
        e.setSubject("Blah subject")
        e.setMessageBody("Blah text", isHTML: false)
        presentViewController(e, animated: true, completion: nil)
        }

    func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?)
        {
        dismissViewControllerAnimated(true, completion: nil)
        }






然而!注意!



这些天发送电子邮件在应用程序中很糟糕。



今天好多了简单地切换到电子邮件客户端。



添加到plist ...


However! Note!

These days it is crappy to send an email "in app".

It's much better today to simply cut away to the email client.

Add to plist ...

<key>LSApplicationQueriesSchemes</key>
 <array>
    <string>instagram</string>
 </array>

然后代码如

func pointlessMarketingEmailForClient()
    {
    let subject = "Some subject"
    let body = "Plenty of <i>email</i> body."

    let coded = "mailto:blah@blah.com?subject=\(subject)&body=\(body)".stringByAddingPercentEncodingWithAllowedCharacters(.URLQueryAllowedCharacterSet())

    if let emailURL:NSURL = NSURL(string: coded!)
        {
        if UIApplication.sharedApplication().canOpenURL(emailURL)
            {
            UIApplication.sharedApplication().openURL(emailURL)
            }
        else
            {
            print("fail A")
            }
        }
    else
        {
        print("fail B")
        }
    }

现在,这比尝试从应用程序内部发送电子邮件要好得多。

These days, that is much better than trying to email from "inside" the app.

再次记住iOS模拟器根本没有电子邮件客户端(也不能发送使用应用程序内的作曲家发送电子邮件)。您必须在设备上进行测试。

Remember again the iOS simulators simply do not have email clients (nor can you send email using the composer within an app). You must test on a device.

这篇关于我对Simulator中的Swift(iOS8)中的MFMailComposeViewController有误解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆