使用MFMailComposeViewController在iOS应用内编辑邮件使用方法及常见问题
来源:互联网 发布:绿联 mac usb网卡驱动 编辑:程序博客网 时间:2024/05/18 02:33
Tips:
在APP中发送邮件,是一个很普遍的应用场景,譬如对于APP的用户反馈,就可以通过在APP中直接编辑邮件或者打开iOS自带的Mail来实现邮件反馈。下面先回顾一下在APP中使用邮件的两种方式,然后再和大家分享一个项目中遇到的问题。
iOS系统框架提供的两种发送Email的方法:openURL 和 MFMailComposeViewController:
Type 1:openURL
openURL调用系统Mail客户端 是我们在iOS3之前实现发邮件功能的主要方法。效果是,从A应用切换到Mail,实际是在Mail中编辑发送邮件,这种方法是很不友好的。
下面是详细代码:
-(void)launchMailApp { NSMutableString *mailUrl = [[[NSMutableString alloc]init]autorelease]; //添加收件人 NSArray *toRecipients = [NSArray arrayWithObject: @"first@example.com"]; [mailUrl appendFormat:@"mailto:%@", [toRecipients componentsJoinedByString:@","]]; //添加抄送 NSArray *ccRecipients = [NSArray arrayWithObjects:@"second@example.com", @"third@example.com", nil]; [mailUrl appendFormat:@"?cc=%@", [ccRecipients componentsJoinedByString:@","]]; //添加密送 NSArray *bccRecipients = [NSArray arrayWithObjects:@"fourth@example.com", nil]; [mailUrl appendFormat:@"&bcc=%@", [bccRecipients componentsJoinedByString:@","]]; //添加主题 [mailUrl appendString:@"&subject=my email"]; //添加邮件内容 [mailUrl appendString:@"&body=<b>email</b> body!"]; NSString* email = [mailUrl stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; [[UIApplication sharedApplication] openURL: [NSURL URLWithString:email]]; }
Type 2:MFMailComposeViewController
MFMailComposeViewController是iOS3之后新增的,源于MessageUI.framework。显而易见,我们通过MFMailComposeViewController这个控制器,可以在我们自己的APP中展现一个邮件编辑页面,这样发送邮件就不需要离开当前的APP了。前提是设备中的Mail要添加了账户,或者iCloud设置了邮件账户。所以需要MFMailComposeViewController提供的canSendMail判断是否已绑定账户。
MFMailComposeViewController使用前的准备:
1、项目中引入MessageUI.framework
2、导入MFMailComposeViewController.h
3、遵循MFMailComposeViewControllerDelegate,并实现代理方法来处理发送
下面是详细代码:
- (void)displayMailPicker { MFMailComposeViewController *mailPicker = [[MFMailComposeViewController alloc] init]; mailPicker.mailComposeDelegate = self; //设置主题 [mailPicker setSubject: @"eMail主题"]; //添加收件人 NSArray *toRecipients = [NSArray arrayWithObject: @"first@example.com"]; [mailPicker setToRecipients: toRecipients]; //添加抄送 NSArray *ccRecipients = [NSArray arrayWithObjects:@"second@example.com", @"third@example.com", nil]; [mailPicker setCcRecipients:ccRecipients]; //添加密送 NSArray *bccRecipients = [NSArray arrayWithObjects:@"fourth@example.com", nil]; [mailPicker setBccRecipients:bccRecipients]; // 添加一张图片 UIImage *addPic = [UIImage imageNamed: @"Icon@2x.png"]; NSData *imageData = UIImagePNGRepresentation(addPic); // png //关于mimeType:http://www.iana.org/assignments/media-types/index.html [mailPicker addAttachmentData: imageData mimeType: @"" fileName: @"Icon.png"]; //添加一个pdf附件 NSString *file = [self fullBundlePathFromRelativePath:@"abc.pdf"]; NSData *pdf = [NSData dataWithContentsOfFile:file]; [mailPicker addAttachmentData: pdf mimeType: @"" fileName: @"abc.pdf"]; NSString *emailBody = @"<font color='red'>eMail</font> 正文"; [mailPicker setMessageBody:emailBody isHTML:YES]; [self presentModalViewController: mailPicker animated:YES]; } #pragma mark - 实现 MFMailComposeViewControllerDelegate - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error { //关闭邮件发送窗口 [self dismissModalViewControllerAnimated:YES]; NSString *msg; switch (result) { // result是枚举类型 case MFMailComposeResultCancelled: msg = @"用户取消编辑邮件"; break; case MFMailComposeResultSaved: msg = @"用户成功保存邮件"; break; case MFMailComposeResultSent: msg = @"用户点击发送,将邮件放到队列中,还没发送"; break; case MFMailComposeResultFailed: msg = @"用户试图保存或者发送邮件失败"; break; default: msg = @""; break; } [self alertWithMessage:msg]; }
目前,使用iOS系统邮件风格的发邮件方式,是对上面两种的结合:
- (void)sendMailWithAddress:(NSArray *)address{ if ([MFMailComposeViewController canSendMail]) { [self displayMailPicker]; //APP内编辑邮件 } else { [self launchMailApp]; // 打开Mail客户端,编辑邮件 }}
Type 3:开源SMTP Client
https://github.com/jetseven/skpsmtpmessage
它的优点是我们不必局限于iOS系统风格的邮件编辑页面,而可以根据自己APP的UI风格定制相应的视图以适应整体的设计
在SKPSMTPMessage类中,并没有对视图进行任何的要求,它提供的都是数据层级的处理,你只需要定义好相应的发送要求就可以实现邮件发送了。至于是以什么样的方式获取这些信息,就可以根据软件的需求来确定交互方式和视图样式了
下面是示例代码:
SKPSMTPMessage *testMsg = [[SKPSMTPMessage alloc] init]; testMsg.fromEmail = @"test@gmail.com"; testMsg.toEmail =@"to@gmail.com"; testMsg.relayHost = @"smtp.gmail.com"; testMsg.requiresAuth = YES; testMsg.login = @"test@gmail.com"; testMsg.pass = @"test"; testMsg.subject = [NSString stringWithCString:"测试" encoding:NSUTF8StringEncoding]; testMsg.bccEmail = @"bcc@gmail.com"; testMsg.wantsSecure = YES; // smtp.gmail.com doesn't work without TLS! // Only do this for self-signed certs! // testMsg.validateSSLChain = NO; testMsg.delegate = self; NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:@"text/plain",kSKPSMTPPartContentTypeKey, [NSString stringWithCString:"测试正文" encoding:NSUTF8StringEncoding], kSKPSMTPPartMessageKey,@"8bit",kSKPSMTPPartContentTransferEncodingKey,nil]; NSString *vcfPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"vcf"]; NSData *vcfData = [NSData dataWithContentsOfFile:vcfPath]; NSDictionary *vcfPart = [NSDictionary dictionaryWithObjectsAndKeys: @"text/directory;\r\n\tx-unix-mode=0644;\r\n\tname=\"test.vcf\"",kSKPSMTPPartContentTypeKey, @"attachment;\r\n\tfilename=\"test.vcf\"",kSKPSMTPPartContentDispositionKey, [vcfData encodeBase64ForData],kSKPSMTPPartMessageKey,@"base64",kSKPSMTPPartContentTransferEncodingKey,nil]; testMsg.parts = [NSArray arrayWithObjects:plainPart,vcfPart,nil]; [testMsg send];
上面就是APP发送邮件的几种方式,那么最近我碰到的坑是什么意思呢?我用了type 1和type 2结合的方式,先描述一下这个bug:
1、iOS7的pad,绑定邮箱账户(Mail和iCloud随便一个),能用type 2打开APP内编辑页面
2、iOS7的pad,不绑定邮箱账户,能用type 1打开Mail客户端
3、iOS8、9的pad,绑定邮箱账户(Mail和iCloud随便一个),无任何反应
4、iOS8、9的pad,不绑定邮箱账户,能用type 1打开Mail客户端
是MFMailComposeViewController在iOS系统版本上有bug吗?后来在stackoverflow上看到,MFMailComposeViewController在父控制器上还有其他视图操作的时候 确实存在着问题,比如我的情况:
[[RootViewController sharedRootViewController] sendMailWithAddress:[mailAddress componentsSeparatedByString:@";"]]; //1 [[RootViewController sharedRootViewController] dismissPopoverWithAnimation:YES]; // 2
第1行就是RootViewController推出MFMailComposeViewController的方法
第2行是RootViewController dismiss掉另一个popoverViewController的方法
那么问题来了,当我发出命令,RootViewController推出MFMailComposeViewController之后,MFMailComposeViewController出现之前,RootViewController又去dismissVC,这就是在搞事情了,造成混乱,导致MFMailComposeViewController还没appear就被dismiss掉了。
问题找到了就好办了,将1、2位置互换:
[[RootViewController sharedRootViewController] dismissPopoverWithAnimation:YES]; [[RootViewController sharedRootViewController] sendMailWithAddress:[mailAddress componentsSeparatedByString:@";"]];
提前将该dismiss的执行了,让推出MFMailComposeViewController之后,尽量避免视图和VC上的变化。
总之,出现这问题,就要检查推出MFMailComposeViewController之后,父控制器上有无其他视图方面的操作。
其实习惯就好,在navigationbar存在的时候,更会出现奇葩问题,,还需小心谨慎!!!
- 使用MFMailComposeViewController在iOS应用内编辑邮件使用方法及常见问题
- IOS使用MFMailComposeViewController发邮件
- iOS开发 MFMailComposeViewController(发送邮件)的使用
- iOS 使用MFMailComposeViewController 报错及解决方案
- iOS应用内购常见问题及注意事项
- 使用MFMailComposeViewController发送邮件时防止崩溃
- 游戏内调用系统邮件,编辑邮件(android + ios)
- MFMailComposeViewController 发邮件
- 发送邮件--MFMailComposeViewController
- IOS-Frameworks-MessageUI-MFMailComposeViewController
- MFMailComposeViewController发送邮件的实例
- MFMailComposeViewController发送邮件的实例
- MFMailComposeViewController发送邮件的实例
- MFMailComposeViewController发送邮件的实例
- MFMailComposeViewController发送邮件的实例
- MFMailComposeViewController发送邮件的实例
- MFMailComposeViewController发送邮件的实例
- 集成邮件发送功能MFMailComposeViewController
- linux socket编程之socket()函数介绍
- deep learning学习资源汇总
- UITableViewCellAccessoryType
- java类与对象_内部类_思维导图总结2
- csviter mxnet
- 使用MFMailComposeViewController在iOS应用内编辑邮件使用方法及常见问题
- Iwfu-安卓传感器(2)使用传感器实现几个小例子
- 数据库优化查询计划的方法
- BigDecimal
- Ubuntu 15.04配置Caffe(cpu)_我遇到的坑
- sqlserver行转列
- Oracle之优化篇---海量数据处理分析
- DrawerLayout侧滑菜单
- 工厂模式(Factory Design Patter)