简体   繁体   English

iOS:已经显示邮件撰写视图时,如何在后台创建/准备自定义电子邮件附件?

[英]iOS: How to create/prepare a custom email attachment in the background when already showing mail compose view?

I'd love to share custom content of my iOS 6.0 app via email. 我想通过电子邮件分享我的iOS 6.0应用程序的自定义内容。

But since my content takes some time to be prepared before I can share it, I can't manage to show the mail compose view immediately when the user presses the 'share' button. 但是由于我的内容需要花费一些时间才能共享,因此当用户按下“共享”按钮时,我无法立即显示邮件撰写视图。 Unfortunately the MFMailComposeViewController needs all attachments right from the start, so I have to wait for the attachment before I can init and show the MFMailComposeViewController (like it's suggested here: UIActivityView attach file to Email ) 不幸的是MFMailComposeViewController从一开始就需要所有附件,因此我必须等待附件才能初始化并显示MFMailComposeViewController(如此处建议的那样: UIActivityView将文件附加到Email

-- Edit after reading Sapan's answer: What I'm looking for is a behavior like UIActivityViewController when sharing eg a video file that yet has to be created: the user presses the share button, and immediately the UIActivityController shows up. -阅读Sapan的答案后进行编辑:共享时,我要寻找的是类似UIActivityViewController的行为,例如尚未创建的视频文件:用户按下共享按钮,并立即显示UIActivityController。 The attachment is created in the background and creation does not interrupt the user's experience. 附件是在后台创建的,创建过程不会中断用户的体验。 -- -

I tried UIActivityViewController with it's nice asynchronous UIActivityItemProvider feature, but unfortunately this only seems to work for attachments with public mime types like images and video. 我尝试了具有不错的异步UIActivityItemProvider功能的UIActivityViewController,但不幸的是,这似乎仅适用于具有图像和视频等公共mime类型的附件。 My custom NSData 'item' simply gets ignored not only for sharing on facebook (which makes perfect sense) but also for email sharing. 我自定义的NSData'item'不仅被忽略,不仅因为在Facebook上共享(很有意义),还因为电子邮件共享而被忽略。 Or am I doing something wrong here: 还是我在这里做错了什么?

MyUIActivityItemProvider *myCustomDocProvider = [[MyUIActivityItemProvider alloc] initWithPlaceholderItem:[[NSData alloc]init] andCustomInfoToCreateNSDataFrom:customAppInfo];
UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:@[myTextString, myCustomDocProvider] applicationActivities:nil];
[self presentViewController:activityVC animated:YES completion:nil];

I'm already thinking about creating my own custom email composer view, so that I can create the attachment in the background while/after the user is typing. 我已经在考虑创建自己的自定义电子邮件编辑器视图,以便可以在用户键入时/之后在后台创建附件。 But I don't want to. 但是我不想。 I like the idea of 'consistency of UI elements' I read about in the HIG. 我喜欢在HIG中读到的“ UI元素的一致性”的想法。

What can I do? 我能做什么?

You can create a method as follows and then invoke it using [self performSelectorInBackground:@selector(sendMail)]; 您可以按照以下方法创建方法,然后使用[self performSelectorInBackground:@selector(sendMail)];调用它[self performSelectorInBackground:@selector(sendMail)];

-(void) sendMail
{
    // Prepare the data

    // Attach the data
    MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
    [picker addAttachmentData:myData mimeType:@"<YOUR-MIME-TYPE>" fileName:@"Filename"];

    // Show compose view controller on the main thread
    dispatch_async(dispatch_get_main_queue(), ^(void) {
        // Fill out the email body text
        NSString *emailBody = @"Body";
        [picker setMessageBody:emailBody isHTML:NO];
        [self presentModalViewController:picker animated:YES];
    });
}

What you can do is set your mail body to HTML with images or media referenced from a remote server. 您可以做的是将您的邮件正文设置为带有从远程服务器引用的图像或媒体的HTML。 Then the user will see a broken image in the mail compose view (perhaps you can hide this using some clever HTML) but at the time the mail is received the upload should be done. 然后,用户将在邮件撰写视图中看到损坏的图像(也许您可以使用一些巧妙的HTML隐藏该图像),但是在收到邮件时,应该完成上传。

Not optimal because it can fail after sending the email but probably your best bet. 并非最佳选择,因为它在发送电子邮件后可能会失败,但可能是最好的选择。

This can be done by using a boolean in your myCustomDocProvider to hold the return of the item until the building of the file is complete. 这可以通过在myCustomDocProvider中使用布尔值来保持项目的返回直到文件的构建完成来完成。 If you want to show progress or have an activity indicator show on your main view, you can do this by calling it from the main thread. 如果要在主视图上显示进度或显示活动指示器,可以通过从主线程调用它来实现。 Here is a code snippet of this in action: 这是实际的代码片段:

Set the Activity View Controller in your provider with this function in order to load a progress view. 使用此功能在提供程序中设置“活动视图控制器”,以便加载进度视图。

self.parentViewController = parentVc;

Here is the item function with blocking and feedback view load. 这是具有阻止和反馈视图加载的项目功能。

self.wait = true;

[self prepareFile:^(){
    [self performSelectorOnMainThread:@selector(dismissProgressView) 
                              withObject:nil waitUntilDone:NO];
}];

[self performSelectorOnMainThread:@selector(loadProgressView) 
                              withObject:nil waitUntilDone:NO];

while (self.wait) {
    [self performSelectorOnMainThread:@selector(updateProgressView) 
                                     withObject:nil waitUntilDone:NO];
}

return self.completedUrl;

You can then create the three functions that are called on main thread to show a progress view, update the progress view while waiting for completion of the file. 然后,您可以创建在主线程上调用的三个函数以显示进度视图,在等待文件完成时更新进度视图。 In the implementation of the dismissProgressView function, make sure to set the wait boolean to false when dismissViewController is complete. 在dismissProgressView函数的实现中,请确保在dismissViewController完成后将wait布尔值设置为false。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM