如何在应用中通过邮件输入和输出数据

这篇文章还可以在这里找到 英语

Load Attachments In Your App!

很多开发者都希望能够通过电子邮件分享他们的应用数据。这对用户用户之间以及设备之间的数据传输来说是一个很方便的方法--它甚至可以为你带来一些新的用户。
幸运的是,在iPhone应用开发里这是很容易实现的 -- 你只需要在Info.plist里设置几个key,并且处理几个回传函数使控制系统可以通过URL引入数据来开启应用。
我们将会在这篇教程里讲解这些是如何实现的。
我们将会由the Scary Bugs项目开始讲解。我们在简单应用教程中开始了这个项目,并且在文件分享教程中对它进行了更新。
如果你还没有这个项目,可以在这里下载。

设定你的Info.plist

我们已经为了支持邮件分享应用数据做了许多准备工作--我们已经写好代码将应用的数据保存了一个独立的副本。
所以下一步需要做的就是设定Info.plist让操作系统知道我们可以处理”Scary Bug 的文件”。具体的操作就是将你的应用注册为可以处理特定UTI,并且将系统不知道的UTI引出。
总的来说,UTI就是代表你的文件的唯一标识符,就如同”com.raywenderlich.scarybugs.sbz”一样。一些常见的文件类型,如”public.jpeg”和”public.html”,还有它们自己的内置UTI。
接下来我们会将应用注册为“可以处理我们自己生成的UTI的应用”,然后我们会将UTI的信息告诉操作系统,比如它所使用的文件扩展名以及它在email编码中所使用的MIME类型。
现在让我们来看看具体怎么操作吧!打开ScaryBugs-Info.plist,并且添加以下条目:

你可以从Apple的UTI手册中查到这些值都是什么含义,但是你要注意以下几点:

  • CFBundleDocumentTypes条目的意思是我们的应用支持那个/些UTI作为所有者/编辑器,在我们的应用中,即为com.raywenderlich.scarybugs.sbz UTI。
  • UTExportedTypeDeclaration条目提供了com.raywenderlich.scarybugs.sbz的信息,因为这并不是一个公用的UTI。也就是说,如果任何文件的后缀为.sbz或者它的mime类型为application/scarybugs,那么它就属于这个我们支持的文件类型。

信不信由你,设置这些keys就是我们让操作系统开始传输后缀为.sbz的应用数据所要做的全部准备工作。你可以通过给自己发送一个 sample bug来进行测试。

如果你想打开Scary Bugs,可以按住附件。如果你这么做了,Scary Bugs就会打开,当然在这里它并不会加载,因为我们还没有加入任何的代码。这就是我们接下来要做的事情。

引入应用数据

当邮件或者其他应用想要给你的应用发送一个文件,可以通过两个方法:通过 application:didFinishLaunchingWithOptions,用 UIApplicationLaunchOptionsURLKey来传递URL,或者通过application:handleOpenURL。
为了理解这些都是在什么时候发生的,你可以看看Oliver Drobnick写的一片非常实用的讲解这些方法在什么时候调用的带图表的文章
现在让我们开始实现吧--这会很简单,因为我们已经做了很多的准备工作。

将下列改动加入ScaryBugDoc.h:

// After @interface- (BOOL)importFromURL:(NSURL *)importURL;

将下列代码加入ScaryBugDoc.m:

// Add new function- (BOOL)importFromURL:(NSURL *)importURL {
    NSData *zippedData = [NSData dataWithContentsOfURL:importURL];    return [self importData:zippedData];    
}

下列代码加入RootViewController.h:

// After @interface- (void)handleOpenURL:(NSURL *)url;

还有将如下代码加入RootViewController.m:

// New method- (void)handleOpenURL:(NSURL *)url {
    [self.navigationController popToRootViewControllerAnimated:YES];
    ScaryBugDoc *newDoc = [[[ScaryBugDoc alloc] init] autorelease];    if ([newDoc importFromURL:url]) {
        [self addNewDoc:newDoc];       
    }}

最后,将下列代码加入ScaryBugsAppDelegate.m:

// Add at end of application:didFinishLaunchingWithOptionsNSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];if (url != nil && [url isFileURL]) {
        [rootController handleOpenURL:url];                
} // Add new method-(BOOL) application:(UIApplication *)application handleOpenURL:(NSURL *)url { 
    RootViewController *rootController = (RootViewController *) [navigationController.viewControllers objectAtIndex:0];    if (url != nil && [url isFileURL]) {
        [rootController handleOpenURL:url];                
    }     
    return YES;
 }

这些都不难理解,但是要注意几点。
首先,我们在ScaryBugDoc中加入了一个方法来将文件从URL引入。从系统中传给我们的这个URL实际上我们应用的目录中的文件的副本。所以我们用NSData来读取它,并将它传给之前写好的importData方法。
在RootViewController中,我们弹回到root view controller(除非我们是在detail view的某处),生成一个新的文件,并从给定的URL引入文件。
在ScaryBugsAppDelegate中,在能够接收到我们需要的URL的地方,如果这是一个文件URL(而不是队列字符串,我们也许以后会有专门的教程讲解),我们会通知root view controller现在可以进行引入了。
现在编译并且运行你的应用吧,如果一切顺利的话,你应该可以打开邮件的附件并且看到引入的应用的bug!

输出应用数据

引入数据是比较难的部分 -- 输出数据将会简单很多。
在EditBugViewController.h中进行如下改动:

// Add to the top of the file#import <MessageUI/MessageUI.h>// Modify EditBugViewController to have two new protocols: UIActionSheetDelegate and MFMailCom[email protected] EditBugViewController : UIViewController <UITextFieldDelegate, RateViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIAlertViewDelegate, UIActionSheetDelegate, MFMailComposeViewControllerDelegate> {

然后在EditBugViewController.m中进行如下改动:

// Replace exportTapped with the following:- (void)exportTapped:(id)sender { 
    UIActionSheet *actionSheet = [[[UIActionSheet alloc]
                                   initWithTitle:@"" 
                                   delegate:self 
                                   cancelButtonTitle:@"Cancel" 
                                   destructiveButtonTitle:nil 
                                   otherButtonTitles:@"Export via File Sharing", @"Export via Email", nil] autorelease];    [actionSheet showInView:self.view];
 }// Add new methods- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {     if (buttonIndex == actionSheet.firstOtherButtonIndex + 0) {         [DSBezelActivityView newActivityViewForView:self.navigationController.navigationBar.superview withLabel:@"Exporting Bug..." width:160];   
        [_queue addOperationWithBlock: ^{
            BOOL exported = [_bugDoc exportToDiskWithForce:FALSE];            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                [DSBezelActivityView removeViewAnimated:YES];                if (!exported) {
                    UIAlertView *alertView = [[[UIAlertView alloc] 
                                               initWithTitle:@"File Already Exists!" 
                                               message:@"An exported bug with this name already exists.  Overwrite?" 
                                               delegate:self 
                                               cancelButtonTitle:@"Cancel" 
                                               otherButtonTitles:@"Overwrite", nil] autorelease];                    [alertView show];                }
            }];        }]; 
     } else if (buttonIndex == actionSheet.firstOtherButtonIndex + 1) {         [DSBezelActivityView newActivityViewForView:self.navigationController.navigationBar.superview withLabel:@"Exporting Bug..." width:160];   
        [_queue addOperationWithBlock: ^{
            NSData *bugData = [_bugDoc exportToNSData];            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                [DSBezelActivityView removeViewAnimated:YES];                if (bugData != nil) {
                    MFMailComposeViewController *picker = [[[MFMailComposeViewController alloc] init] autorelease];                    [picker setSubject:@"My Scary Bug"];                    [picker addAttachmentData:bugData mimeType:@"application/scarybugs" fileName:[_bugDoc getExportFileName]];                    [picker setToRecipients:[NSArray array]];                    [picker setMessageBody:@"Check out this scary bug!  You‘ll need a copy of ScaryBugs to view this file, then tap and hold to open." isHTML:NO];                    [picker setMailComposeDelegate:self];                    [self presentModalViewController:picker animated:YES];                    
                }             }];        }]; 
     } }- (void)mailComposeController:(MFMailComposeViewController *)controller
		  didFinishWithResult:(MFMailComposeResult)result
						error:(NSError *)error {
    [self dismissModalViewControllerAnimated:YES];}

在这里我们改变了输出按键弹出窗口询问用户希望通过之前一样的文件分享还是电子邮件来输出。
如果用户选择通过邮箱分享文件,我们会使用MFMailComposeViewController来生成一个邮件信息,并且加入含有bug数据的附件。是不是很简单?
我们开始测试前的最后一件事情:右键单击Frameworks,选择”AddExisting Framework…”,并从下拉列表中选择”MessageUI.framework”。
下面就编译运行你的应用吧,你应该已经可以通过邮件自动的从应用输出一个“Scary Bug”了!

来点好玩的!

如果你已经做了这么多,何不来点更好玩的?
通过应用来生成一个Scary Bug,然后把它用邮件发送给我,邮箱地址在上图的截图中,我会把它加入这片教程!让我们看看我们都制造了什么恐怖的生物!:]
更新: 这是一个由Alex Hedley发来的不怎么恐怖bug!:]

何去何从?

这里 就是我们这个教程系列到目前为止的代码。
我的计划是Scary Bugs应用就这么多了,但是谁知道呢,也许我会再增加点什么。
同时,如果你有什么问题,评论,或者你想分享你觉得什么bug最恐怖,请让我知道!:]

另外一篇文章也不错:

http://blog.spritebandits.com/2011/12/14/importing-csv-data-file-into-an-ios-app-via-email-attachment/

http://blog.spritebandits.com/2011/12/21/importing-csv-data-file-into-an-ios-app-via-email-attachment-part-2/

如何在应用中通过邮件输入和输出数据

时间: 2024-11-08 18:39:02

如何在应用中通过邮件输入和输出数据的相关文章

java中从控制台输入多行数据 按回车键输入空行结束

这篇博文是用Windows Live Writer写的,看看效果 下面是以前写的程序:java中从控制台输入多行数据 按回车键输入空行结束 //试过几个插件,发现插入代码后都不能复制, 但是插入图片还是很方便的, 用wlw写博客好处是可以离线, 以后就用wlw写,然后发布草稿,再到CSDN插入代码后发表文章,只是写个博客要这么艰难吗!!! <pre name="code" class="java">Scanner scanner = new Scanne

2. Python中的基本输入、输出、格式化

本文利用的是Python 3.x版本,建议学习3.x版本 Python中的基本输入.输出.格式化 1. 输入 使用input([prompt])读取一行,将其转换为string类型并返回,input的参数可有可无,如果有参数的话,会在控制台(可以这样理解)输出参数的内容,不换行.通常情况下我们在控制台输入一些数据,然后敲击回车,就完成了本次输入.以下是例子. name = input("Enter your name: ") print(name) 这里要注意的是,input返回的是s

C#之各类控件中输入、输出数据

本文重点讲的是:ComboBox.DateTimePicker.TextBox.RadioButton.DataGridView这五种控件的输入和输出. 一.控件数据的输入: (1)ComboBox控件中的下拉列表中,可以显示多项数据,使用ComboBox控件中的Items集合的Add方法向控件中添加数据.如下图: (2)DateTimePicker控件,一般用于让用户可以从日期列表中选择单个值.运行时,单击控件边上的下拉箭头,会显示两个部分:一个下拉列表,一个用于选择日期.如下图: (3)Te

C++学习笔记之输入、输出和文件

一.流的概念 数据从内存的一个地址移动到另一个地址称为数据流动——流操作 流操作是通过缓冲区(buffer)机制实现的. 缓冲区:内存的一块区域——用作文件与内存交换数据. 数据从文件中读出:文件 → 缓冲区 → 内存 将数据写入文件:内存 → 缓冲区 → 文件 为什么要使用缓冲区而不直接从文件中读取数据到内存或者直接有内存写入文件呢?我们的文件通常都存在磁盘中,程序从磁盘读取一个字符需要大量的硬件活动,速度非常慢.缓冲方法则从磁盘上读取大量信息,将这些信息存储在缓冲区,然后每次从缓冲区里读取一

WORD中利用“邮件合并”插入照片

1.建好EXCEL表,照片地址必须用绝对地址,如:E:\\ABC\\CEF\\abcd.jpg这样的格式(在Excel中搞定图片地址): 2.在WORD中打开“邮件合并”工具栏,在数据源中打开相应的EXCEL文件: 3.在要插照片处,先打开“插入”菜单“域”命令,在“域名”项中选择“includepicture”,然后在对话框中间的“文件名”处随便输入几个字母: 4.此时文档中会显示个图像占位符,选中,按alt+F9(域代码切换),看到代码,将刚才的几个字母选中,再点“邮件合并”工具栏中的“插入

Office 365中的邮件跟踪(Exchange Online)

在Office 365中调用邮件跟踪是管理员用来监视电子邮件流的最基本的工具之一.由于电子邮件是通过Office 365的EOP传递的,因此有关这些邮件的信息将存储在日志中,并可用于管理目的.无论用户是否删除或清除邮件,管理员都可以查看发送和接收邮件的基本信息. 消息跟踪不允许您查看到邮件的内容.不过,它可以提供很多关于电子邮件的重要数据: 发件人和收件人 发送和接收日期 主题和大小 事件的状态和细节.状态字段中有六个可能的值:提交,失败,挂起,隔离,过滤为垃圾邮件和未知. 用于发送消息的IP地

Linux中Postfix邮件认证配置(五)

Postfix+Dovecot+Sasl工作原理 1.A用户使用MUA客户端借助smtp协议登陆smtpd服务器,需要先进行用户和密码认证,而SMTPD服务器端支持sasl认证,例如有一个sasl客户端,就会去连接SASL.当SASL接受到验证请求时就会根据验证方式去进行验证,常用的有PAM,passwd等.验证成功后就会返回给Smtpd服务器.而smtpd就会允许A用户登陆发送邮件. 2.Smtpd服务器接受到邮件转发请求后,查看邮件是本域的还是外部域的,如果是本域内的用户,就会开启MDA进程

CString中Format函数与格式输入与输出

CString中Format函数与格式输入与输出 Format是一个很常用,却又似乎很烦的方法,以下是它的完整概貌,以供大家查询之用: 格式化字符串forma("%d",12)意思是将一个整形的格式化的字符(我认为是保持其形状不变) 1).格式说明总是以%字符开始,以下是不同类型数据的格式方式%号后的说明: d输出带符号十进制数 o输出无符号八进制数 x输出无符号十六进制数 u输出无符号数 c输出单个字符 s输出一串字符 f输出实数(6位小数) e以指数形式输出实数 g选用f与e格式中

vector中元素的输入和终止

在Essential C++一书课后题1-6的答案中,有了新的发现. 题目概述为: 编写一个程序,从标准输入设备读取一段整数,并将读入的整数依次放到array及vector中,然后遍历这两种容器,求取数值总和.将总和及平均值输出至标准输出设备. 答案代码: //用vector 解决问题#include<iostream>#include<vector>           //用vector方式的头文件using namespace std; int main(){ vector&