我们在日常使用移动应用产品时经常会遇到正在使用的这款APP在操作中经常会跳转到另一款APP中去操作,比如支付宝支付,微信支付,微博分享等。这不禁让我们联想到苹果的沙盒机制,受苹果的这一机制影响,我们不能应用之间资源共享,也就是说我们的应用都是独立的块,应用内所需要的资源都是自给自足不受外界的”救济”,那么应用之间通信的行为就是通过URL Schemes来实现的。
URL Schemes
我们通过对比网页链接来理解iOS上的 URL Schemes。
URL Schemes有两个单词:
- URL:链接地址或网址,
https://www.baidu.com就是一个URL。 - Schemes:表示的是URL中的最初位置,即
://之前的那段字符,比如https://www.baidu.com这个URL的Schemes就是https。
根据上面对URL Schemes的理解,我们在iOS中如果想定位到某个APP,只需要知道 Schemes 部分就可以做到了,比如我们要打开微信这个APP,我们只需要知道微信的 Schemes 是 wexin ,在后面拼接上 :// 即: wexin://
然后在 safari 浏览器输入网址的地方输入 wexin:// 确认后就会在屏幕中弹出 在"微信"中打开链接吗? 的提示框,当你选择打开操作后就会自动跳转到微信界面了。
目前我们仅仅是定位到了某个APP,如果想跳转到这个APP并让它做一些我们想要的操作的话,我们需要在://后面跟一些路径参数让它定位到具体的功能或页面:
| 网页(百度) | iOS应用(微信) |
|---|---|
| 网站首页: https://www.baidu.com | 打开应用: wexin:// |
| 子页面: https://www.baidu.com/duty(百度免责声明页面) | wexin://dl/moments (朋友圈) |
通过上面的表格对比异同:
- 不同点:定位到网站首页需要一个完整的URL,而定位某个应用需要
Schemes后面拼接上://。 - 相同点:网站定位到具体的某个页面都需要提供路径,比如定位到百度的免责声明页面需要在
https://www.baidu.com后面拼接/duty,iOS应用中定位到APP的具体功能或页面需要在wexin://后面拼接dl/moments。
补充:
- 苹果没有硬性要求APP必须要有URL Schemes,所以我们所装的APP不是每一款都会有`URL Schemes,即使有URL Schemes也仅仅是能让我们从自己的应用A跳转到另一个应用B,如果想跳转到应用B后再根据你传递的内容跳转到具体的页面或执行某些功能,那么要看应用B的开发者是否制定了统一的参数规则在里面。
- 苹果没有要求URL Schemes是唯一的,所以不是每一个URL Schemes都对应一款应用,如果两个应用拥有相同的URL Schemes,当你通过这个URL Schemes去打开应用的时候,它会打开最后安装的那款APP。实践:你新建一个工程设置URL Schemes和支付宝的相同为
alipay,当你用饿了么订餐下单并通过支付宝支付的时候,发现跳转的是你生成的APP,因为支付宝在你的工程之前安装的。基于这一特性,曾经也出现过 App 使用支付宝的 URL Schemes 拦截支付帐号和密码的事件。
使用
场景:假设我们要从应用URLSchemesB跳转到应用URLSchemesA,并要求应用URLSchemesA 弹出一个新的控制器,并根据传递的参数改变控制器的背景颜色,接下来我们来实现这一过程:
1.分别新创建URLSchemesA和URLSchemesB两个工程项目
2.在URLSchemesA工程的target->info中最下方的URL Types条目中新增URL Schemes:
3.然后在URLSchemesA工程info.plist文件中查看:
可以发现URL Schemes是一个数组,所以在它下面可以添加很多个Item,比方说我们又新增了一个URLSchemesAA,这样做是允许的,说明我们不仅可以通过URLSchemesA://打开APP,还可以使用URLSchemesAA://打开APP,就像微信一样自定义了很多URL Schemes,例如:weixin://,wechat://等。
4.由于我们要实现的不仅仅是简单的跳转过程,还包括跳转后 弹出控制器 + 改变控制器的背景色,所以我们要对URL制定统一规范(scheme://[target]/[action]?[params]),target指的是某个类,action指的是该类的具体方法,params指的是参数,根据这种规范我们生成符合我们要求的URL:URLSchemesA://SecondVC/setupBackgroundColorParmas?color=blueColor,具体代码如下:
1 | - (IBAction)clickedOpenURLSchemesA:(id)sender { |
首先要用canOpenURL:方法判断是否可以打开指定的URL,如果手机中没有这个URL Schemes的应用,会返NO。还有就是iOS9之后,如果没有在info.plist中添加白名单,结果也会返回NO,并且会在控制台输出
1 | canOpenURL: failed for URL: "URLSchemesA://" - error: "This app is not allowed to query for scheme URLSchemesA" |
这就需要我们把URLSchemesA添加到URLSchemesB工程的info.plist的白名单中:
5.当跳转到URLSchemesA时,如果是iOS9之前会调用AppDelegate类中的application:openURL:sourceApplication:annotation:方法,iOS9之后会调用application:openURL:options:方法,偷下懒- -,我就只写在application:openURL:options:了,代码如下:
1 | // AppDelegate.m |
1 | // SecondVC.m |
当然,上述的这个简单例子只是我临时编造的一个情景,意在说明应用之间能够通过自定义URL Schemes来以这种方式通信,实际的使用情景比这要复杂的多,可能渗透到各个功能及业务模块之间,推荐大家看一下Casa Taloyum的组件化方案,其中也有谈及到应用之间的各模块调用。
这样就大工告成啦!Demo已上传至Github请点击这里查看。
相关技能
如何获得手机中应用的URL Schemes?
以微信为例:
- 首先用电脑打开
iTunes,然后在商店搜索微信并下载下来。 - 在资料库的iPhone应用中找到微信应用,右键在Finder中显示:

- 找到
微信 6.5.5.ipa包所在目录后开始解压:
- 解压后在
Payload文件下找到WeChat.app文件,右键显示包内容:
- 在wechat.app中搜索
.plist文件:
- 在搜索到的众多info.plist中所搜
URLSchemes关键字:
参考文献: