首先贴一个链接,本文主要参考了该博客,结合自己的理解写了小Demo并说一说个人的理解:IOS-应用之间调用
每个iOS开发者都知道在iOS系统中各个程序是高度相互独立的Sandbox机制,所以程序之间交流数据甚至程序A调用程序B这种事似乎是有点遥远的事,但是苹果官方也提供了方法让我们去实现。
就个人理解来看,原理非常简单,就是通过App A的AppA-info.plist文件为本程序建立一个对外接口,然后App B通过该接口调用App A。例如Safari浏览器的接口就是http,如果要在程序App中打开Safari浏览器,只要在App中用代码打开URL:http://www.youkuaiyun.com(为csdn卖个广告)就可以了,其中http指定我们要打开的是Safari(该浏览器的对外程序接口),后面的www.youkuaiyun.com就是我们通过Safari浏览器对应的一个子功能的接口打开的URL。
系统程序的接口见Apple URL Scheme Reference。
好了,原理说完了,下面说说利用该功能实现的一个简单的Demo:
先看看故事板,只有一个视图控制器:
头文件的代码如下:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
- (IBAction)openSafari:(id)sender;
- (IBAction)openHelloApp:(id)sender;
@property (weak, nonatomic) IBOutlet UITextField *phoneNumber_textField;
- (IBAction)phone:(id)sender;
@property (weak, nonatomic) IBOutlet UITextField *message_textField;
- (IBAction)sendMessage:(id)sender;
@end
实现代码如下:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tapInView = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard:)];
[self.view addGestureRecognizer:tapInView];
}
- (void)hideKeyboard:(id)sender {
[self.phoneNumber_textField resignFirstResponder];
[self.message_textField resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)openSafari:(id)sender {
NSURL *safariURL = [NSURL URLWithString:@"http://www.youkuaiyun.com"];
[[UIApplication sharedApplication] openURL:safariURL];
}
- (IBAction)openHelloApp:(id)sender {
NSURL *url = [NSURL URLWithString:@"hello://subhello"];
[[UIApplication sharedApplication] openURL:url];
}
- (IBAction)phone:(id)sender {
self.phoneNumber_textField.keyboardType = UIKeyboardTypePhonePad;
NSString *phoneNumber = nil;
if (self.phoneNumber_textField.text && ![self.phoneNumber_textField.text isEqualToString:@""]) {
phoneNumber = self.phoneNumber_textField.text;
}
NSString *urlString = [NSString stringWithFormat:@"tel://%@", phoneNumber];
NSURL *phoneURL = [NSURL URLWithString:urlString];
[[UIApplication sharedApplication] openURL:phoneURL];
}
- (IBAction)sendMessage:(id)sender {
self.message_textField.keyboardType = UIKeyboardTypePhonePad;
NSString *phoneNumber = nil;
if (self.message_textField.text && ![self.message_textField.text isEqualToString:@""]) {
phoneNumber = self.message_textField.text;
}
NSString *urlString = [NSString stringWithFormat:@"sms://%@", phoneNumber];
NSURL *messageURL = [NSURL URLWithString:urlString];
[[UIApplication sharedApplication] openURL:messageURL];
}
@end
Run(注意真机调试,否则无法使用拨号和短信功能):
首先是程序界面:
点击打开Safari按钮,程序将打开Safari浏览器并转到优快云主页:
再点击打开HelloApp,程序将打开另一个接口名为Hello的程序(关于自定义程序的对外接口将在下面补充),该程序的ViewController的背景颜色为绿色:
接着在拨号按钮上面的输入框中输入联系人的电话号码,然后点击拨号按钮:
然后就弹出通话状态了(很牛叉,这样我们就可以自己做一个拨号器了):
还有一个发短信,功能差不多,先输入联系人号码,然后点击发信息按钮:
接着弹出发送信息的界面:
的确,这种直接调用系统或自己写的程序的方式功能是非常强大的,而且实现也非常简单,只需要简单的设定程序的接口URL和用UIApplication调用就可以了。
还有一个问题,怎么自定义我们自己程序的对外接口呢?答案是修改程序的-Info.plist文件:
参考博文中根据官方文档这样给出CFBundleURLTypes的定义:
键 | 值 |
---|---|
| 这是个字符串,表示URL类型的抽象名。为了确保其唯一性,建议您使用反向DNS风格的标识,比如 这里提供的URL类型名是一个指向本地化字符串的键,该字符串位于本地化语言包子目录中的 |
| 这是个URL模式的数组,表示归属于这个URL类型的URL。每个模式都是一个字符串。属于指定URL类型的URL都带有它们的模式组件 |
其中URL Schemes指定程序的对外接口,URL identifier指定子功能接口用于唯一标识该接口,后面紧跟着的就是要打开的URL。例如Safari对外的主要接口是http,子接口例如www.youkuaiyun.com,调用方法就是http://www.youkuaiyun.com,即[URL Scheme]://[URL identifier](某些系统的App是不需要//的,但是有//没有问题),通过这种唯一的URL标识我们可以指定打开外部程序后想要获取的服务。
后面还有程序被外部程序打开后的处理方法:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSLog(@"%@", url.scheme);
return YES;
}
当外部程序调用本程序时是否要处理的方法。
如果下列方法
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
已经被实现,那么handleOpenURL方法不会被执行(被后者覆盖)。
如果返回NO将不会执行delegate的will/didFinishLauchingWithOptions方法,但程序依然被打开。
好吧,对于这部分内容还有很多方面我只是一知半解的,只是大概知道了怎么用而已。
详情请参考我开头给出的链接。
Demo已经上传,有兴趣的可以下载来看看。