iOS开发——高级技术&系统应用于系统服务
系统应用于系统服务
系统应用
在开发某些应用时可能希望能够调用iOS系统内置的电话、短信、邮件、浏览器应用,此时你可以直接使用UIApplication的OpenURL:方法指定特定的协议来打开不同的系统应用。常用的协议如下:
打电话:tel:或者tel://、telprompt:或telprompt://(拨打电话前有提示)
发短信:sms:或者sms://
发送邮件:mailto:或者mailto://
启动浏览器:http:或者http://
1 下面以一个简单的demo演示如何调用上面几种系统应用:
2 //
3 // ViewController.m
4 // iOSSystemApplication
5 //
6 // Created by Kenshin Cui on 14/04/05.
7 // Copyright (c) 2014年 cmjstudio. All rights reserved.
8 //
9 #import "ViewController.h"
10 @interface ViewController ()
11 @end
12 @implementation ViewController
13 - (void)viewDidLoad {
14 [super viewDidLoad];
15 }
16 #pragma mark - UI事件
17 //打电话
18 - (IBAction)callClicK:(UIButton *)sender {
19 NSString *phoneNumber=@"18500138888";
20 // NSString *url=[NSString stringWithFormat:@"tel://%@",phoneNumber];//这种方式会直接拨打电话
21 NSString *url=[NSString stringWithFormat:@"telprompt://%@",phoneNumber];//这种方式会提示用户确认是否拨打电话
22 [self openUrl:url];
23 }
24 //发送短信
25 - (IBAction)sendMessageClick:(UIButton *)sender {
26 NSString *phoneNumber=@"18500138888";
27 NSString *url=[NSString stringWithFormat:@"sms://%@",phoneNumber];
28 [self openUrl:url];
29 }
30 //发送邮件
31 - (IBAction)sendEmailClick:(UIButton *)sender {
32 NSString *mailAddress=@"kenshin@hotmail.com";
33 NSString *url=[NSString stringWithFormat:@"mailto://%@",mailAddress];
34 [self openUrl:url];
35 }
36 //浏览网页
37 - (IBAction)browserClick:(UIButton *)sender {
38 NSString *url=@"http://www.cnblogs.com/kenshincui";
39 [self openUrl:url];
40 }
41 #pragma mark - 私有方法
42 -(void)openUrl:(NSString *)urlStr{
43 //注意url中包含协议名称,iOS根据协议确定调用哪个应用,例如发送邮件是“sms://”其中“//”可以省略写成“sms:”(其他协议也是如此)
44 NSURL *url=[NSURL URLWithString:urlStr];
45 UIApplication *application=[UIApplication sharedApplication];
46 if(![application canOpenURL:url]){
47 NSLog(@"无法打开\"%@\",请确保此应用已经正确安装.",url);
48 return;
49 }
50 [[UIApplication sharedApplication] openURL:url];
51 }
52 @end
不 难发现当openURL:方法只要指定一个URL Schame并且已经安装了对应的应用程序就可以打开此应用。当然,如果是自己开发的应用也可以调用openURL方法来打开。假设你现在开发了一个应用 A,如果用户机器上已经安装了此应用,并且在应用B中希望能够直接打开A。那么首先需要确保应用A已经配置了Url Types,具体方法就是在plist文件中添加URL types节点并配置URL Schemas作为具体协议,配置URL identifier作为这个URL的唯一标识,如下图:
然后就可以调用openURL方法像打开系统应用一样打开第三方应用程序了:
1 //打开第三方应用
2 - (IBAction)thirdPartyApplicationClick:(UIButton *)sender {
3 NSString *url=@"cmj://myparams";
4 [self openUrl:url];
5 }
就 像调用系统应用一样,协议后面可以传递一些参数(例如上面传递的myparams),这样一来在应用中可以在AppDelegate的 -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url
1 sourceApplication:(NSString *)sourceApplication annotation:(id)annotation代理方法中接收参数并解析。
2 -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
3 NSString *str=[NSString stringWithFormat:@"url:%@,source application:%@,params:%@",url,sourceApplication,[url host]];
4 NSLog(@"%@",str);
5 return YES;//是否打开
6 }
系统服务
短信与邮件
调 用系统内置的应用来发送短信、邮件相当简单,但是这么操作也存在着一些弊端:当你点击了发送短信(或邮件)操作之后直接启动了系统的短信(或邮件)应用程 序,我们的应用其实此时已经处于一种挂起状态,发送完(短信或邮件)之后无法自动回到应用界面。如果想要在应用程序内部完成这些操作则可以利用iOS中的 MessageUI.framework,它提供了关于短信和邮件的UI接口供开发者在应用程序内部调用。从框架名称不难看出这是一套UI接口,提供有现 成的短信和邮件的编辑界面,开发人员只需要通过编程的方式给短信和邮件控制器设置对应的参数即可。
在 MessageUI.framework中主要有两个控制器类分别用于发送短信(MFMessageComposeViewController)和邮件 (MFMailComposeViewController),它们均继承于UINavigationController。由于两个类使用方法十分类 似,这里主要介绍一下MFMessageComposeViewController使用步骤:
-
创建MFMessageComposeViewController对象。
-
设置收件人recipients、信息正文body,如果运行商支持主题和附件的话可以设置主题subject、附件attachments(可以通过canSendSubject、canSendAttachments方法判断是否支持)
-
设 置代理messageComposeDelegate(注意这里不是delegate属性,因为delegate属性已经留给 UINavigationController,MFMessageComposeViewController没有覆盖此属性而是重新定义了一个代 理),实现代理方法获得发送状态。
下面自定义一个发送短信的界面演示MFMessageComposeViewController的使用:
用 户通过在此界面输入短信信息点击“发送信息”调用MFMessageComposeViewController界面来展示或进一步编辑信息,点击 MFMessageComposeViewController中的“发送”来完成短信发送工作,当然用户也可能点击“取消”按钮回到前一个短信编辑页 面。
实现代码:
1 //
2 // KCSendMessageViewController.m
3 // iOSSystemApplication
4 //
5 // Created by Kenshin Cui on 14/04/05.
6 // Copyright (c) 2014年 cmjstudio. All rights reserved.
7 //
8 #import "KCSendMessageViewController.h"
9 #import
10 @interface KCSendMessageViewController ()
11 @property (weak, nonatomic) IBOutlet UITextField *receivers;
12 @property (weak, nonatomic) IBOutlet UITextField *body;
13 @property (weak, nonatomic) IBOutlet UITextField *subject;
14 @property (weak, nonatomic) IBOutlet UITextField *attachments;
15 @end
16 @implementation KCSendMessageViewController
17 #pragma mark - 控制器视图方法
18 - (void)viewDidLoad {
19 [super viewDidLoad];
20
21 }
22 #pragma mark - UI事件
23 - (IBAction)sendMessageClick:(UIButton *)sender {
24 //如果能发送文本信息
25 if([MFMessageComposeViewController canSendText]){
26 MFMessageComposeViewController *messageController=[[MFMessageComposeViewController alloc]init];
27 //收件人
28 messageController.recipients=[self.receivers.text componentsSeparatedByString:@","];
29 //信息正文
30 messageController.body=self.body.text;
31 //设置代理,注意这里不是delegate而是messageComposeDelegate
32 messageController.messageComposeDelegate=self;
33 //如果运行商支持主题
34 if([MFMessageComposeViewController canSendSubject]){
35 messageController.subject=self.subject.text;
36 }
37 //如果运行商支持附件
38 if ([MFMessageComposeViewController canSendAttachments]) {
39 /*第一种方法*/
40 //messageController.attachments=...;
41
42 /*第二种方法*/
43 NSArray *attachments= [self.attachments.text componentsSeparatedByString:@","];
44 if (attachments.count>0) {
45 [attachments enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
46 NSString *path=[[NSBundle mainBundle]pathForResource:obj ofType:nil];
47 NSURL *url=[NSURL fileURLWithPath:path];
48 [messageController addAttachmentURL:url withAlternateFilename:obj];
49 }];
50 }
51
52 /*第三种方法*/
53 // NSString *path=[[NSBundle mainBundle]pathForResource:@"photo.jpg" ofType:nil];
54 // NSURL *url=[NSURL fileURLWithPath:path];
55 // NSData *data=[NSData dataWithContentsOfURL:url];
56 /**
57 * attatchData:文件数据
58 * uti:统一类型标识,标识具体文件类型,详情查看:帮助文档中System-Declared Uniform Type Identifiers
59 * fileName:展现给用户看的文件名称
60 */
61 // [messageController addAttachmentData:data typeIdentifier:@"public.image" filename:@"photo.jpg"];
62 }
63 [self presentViewController:messageController animated:YES completion:nil];
64 }
65 }
66 #pragma mark - MFMessageComposeViewController代理方法
67 //发送完成,不管成功与否
68 -(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result{
69 switch (result) {
70 case MessageComposeResultSent:
71 NSLog(@"发送成功.");
72 break;
73 case MessageComposeResultCancelled:
74 NSLog(@"取消发送.");
75 break;
76 default:
77 NSLog(@"发送失败.");
78 break;
79 }
80 [self dismissViewControllerAnimated:YES completion:nil];
81 }
82 @end
这里需要强调一下:
-
MFMessageComposeViewController的代理不是通过delegate属性指定的而是通过messageComposeDelegate指定的。
-
可以通过几种方式来指定发送的附件,在这个过程中请务必指定文件的后缀,否则在发送后无法正确识别文件类别(例如如果发送的是一张jpg图片,在发送后无法正确查看图片)。
-
无 论发送成功与否代理方法-(void)messageComposeViewController: (MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result都会执行,通过代理参数中的result来获得发送 状态。
其实只要熟悉了MFMessageComposeViewController之后,那么用于发送邮件的 MFMailComposeViewController用法和步骤完全一致,只是功能不同。下面看一下 MFMailComposeViewController的使用:
1 //
2 // KCSendEmailViewController.m
3 // iOSSystemApplication
4 //
5 // Created by Kenshin Cui on 14/04/05.
6 // Copyright (c) 2014年 cmjstudio. All rights reserved.
7 //
8 #import "KCSendEmailViewController.h"
9 #import
10 @interface KCSendEmailViewController ()
11 @property (weak, nonatomic) IBOutlet UITextField *toTecipients;//收件人
12 @property (weak, nonatomic) IBOutlet UITextField *ccRecipients;//抄送人
13 @property (weak, nonatomic) IBOutlet UITextField *bccRecipients;//密送人
14 @property (weak, nonatomic) IBOutlet UITextField *subject; //主题
15 @property (weak, nonatomic) IBOutlet UITextField *body;//正文
16 @property (weak, nonatomic) IBOutlet UITextField *attachments;//附件
17 @end
18 @implementation KCSendEmailViewController
19 - (void)viewDidLoad {
20 [super viewDidLoad];
21 }
22 #pragma mark - UI事件
23 - (IBAction)sendEmailClick:(UIButton *)sender {
24 //判断当前是否能够发送邮件
25 if ([MFMailComposeViewController canSendMail]) {
26 MFMailComposeViewController *mailController=[[MFMailComposeViewController alloc]init];
27 //设置代理,注意这里不是delegate,而是mailComposeDelegate
28 mailController.mailComposeDelegate=self;
29 //设置收件人
30 [mailController setToRecipients:[self.toTecipients.text componentsSeparatedByString:@","]];
31 //设置抄送人
32 if (self.ccRecipients.text.length>0) {
33 [mailController setCcRecipients:[self.ccRecipients.text componentsSeparatedByString:@","]];
34 }
35 //设置密送人
36 if (self.bccRecipients.text.length>0) {
37 [mailController setBccRecipients:[self.bccRecipients.text componentsSeparatedByString:@","]];
38 }
39 //设置主题
40 [mailController setSubject:self.subject.text];
41 //设置内容
42 [mailController setMessageBody:self.body.text isHTML:YES];
43 //添加附件
44 if (self.attachments.text.length>0) {
45 NSArray *attachments=[self.attachments.text componentsSeparatedByString:@","] ;
46 [attachments enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
47 NSString *file=[[NSBundle mainBundle] pathForResource:obj ofType:nil];
48 NSData *data=[NSData dataWithContentsOfFile:file];
49 [mailController addAttachmentData:data mimeType:@"image/jpeg" fileName:obj];//第二个参数是mimeType类型,jpg图片对应image/jpeg
50 }];
51 }
52 [self presentViewController:mailController animated:YES completion:nil];
53
54 }
55 }
56 #pragma mark - MFMailComposeViewController代理方法
57 -(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
58 switch (result) {
59 case MFMailComposeResultSent:
60 NSLog(@"发送成功.");
61 break;
62 case MFMailComposeResultSaved://如果存储为草稿(点取消会提示是否存储为草稿,存储后可以到系统邮件应用的对应草稿箱找到)
63 NSLog(@"邮件已保存.");
64 break;
65 case MFMailComposeResultCancelled:
66 NSLog(@"取消发送.");
67 break;
68
69 default:
70 NSLog(@"发送失败.");
71 break;
72 }
73 if (error) {
74 NSLog(@"发送邮件过程中发生错误,错误信息:%@",error.localizedDescription);
75 }
76 [self dismissViewControllerAnimated:YES completion:nil];
77 }
78 @end
运行效果: