首先贴一个链接,本文主要参考了该博客,结合自己的理解写了小Demo并说一说个人的理解:IOS-应用之间调用
每个iOS开发者都知道在iOS系统中各个程序是高度相互独立的Sandbox机制,所以程序之间交流数据甚至程序A调用程序B这种事似乎是有点遥远的事,但是苹果官方也提供了方法让我们去实现。
就个人理解来看,原理非常简单,就是通过App A的AppA-info.plist文件为本程序建立一个对外接口,然后App B通过该接口调用App A。例如Safari浏览器的接口就是http,如果要在程序App中打开Safari浏览器,只要在App中用代码打开URL:http://www.csdn.net(为csdn卖个广告)就可以了,其中http指定我们要打开的是Safari(该浏览器的对外程序接口),后面的www.csdn.net就是我们通过Safari浏览器对应的一个子功能的接口。
系统程序的接口见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.csdn.net"]; [[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浏览器并转到CSDN主页:
再点击打开HelloApp,程序将打开另一个接口名为Hello的程序(关于自定义程序的对外接口将在下面补充),该程序的ViewController的背景颜色为绿色:
接着在拨号按钮上面的输入框中输入联系人的电话号码,然后点击拨号按钮:
然后就弹出通话状态了(很牛叉,这样我们就可以自己做一个拨号器了):
还有一个发短信,功能差不多,先输入联系人号码,然后点击发信息按钮:
接着弹出发送信息的界面:
的确,这种直接调用系统或自己写的程序的方式功能是非常强大的,而且实现也非常简单,只需要简单的设定程序的接口URL和用UIApplication调用就可以了。
还有一个问题,怎么自定义我们自己程序的对外接口呢?答案是修改程序的-Info.plist文件:
参考博文中根据官方文档这样给出CFBundleURLTypes的定义:
键 |
值 |
---|---|
|
这是个字符串,表示URL类型的抽象名。为了确保其唯一性,建议您使用反向DNS风格的标识,比如
这里提供的URL类型名是一个指向本地化字符串的键,该字符串位于本地化语言包子目录中的 |
|
这是个URL模式的数组,表示归属于这个URL类型的URL。每个模式都是一个字符串。属于指定URL类型的URL都带有它们的模式组件 |
其中URL Schemes指定程序的对外接口,URL identifier指定子功能接口。例如Safari对外的主要接口是http,子接口例如www.csdn.net,调用方法就是http://www.csdn.net,即[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已经上传,有兴趣的可以下载来看看。