iOS 应用之间的跳转(OC&Swift)
一、应用间跳转介绍
- 1.1、什么是应用间跳转,有什么作用? 如下
- <1>、使用第三方用户登录,需要用户授权,还需要"返回到调用的程序,同时返回授权的用户名"
- <2>、应用程序推广,设置-推荐应用-有很多应用程序图标如果本机已经安装过,会直接跳转到另外一个应用程序, 软件的广告,我们在抖音或者进入头条都可以看到很多的点击事件进去其他的app或者去下载appstore下载app
- <3>、平时 支付宝,微信支付 等等
- 1.2、如何实现应用程序间跳转 ?
-
<1>、跳转appstore进入自己的app: 在我们自己的app里面有时候我们会有更新提醒,其实也就是打开我们自己 app 的
url
,以itms-apps://
或https://
开头的应用详情页链接,跳转到AppStore,如下,其中url要进行转码,下面我就不再转码了
OC 版本:NSURL *url = [NSURL URLWithString:@"itms-apps://itunes.apple.com/app/id1129144823"]; // 注意: 跳转之前, 可以使用 canOpenURL: 判断是否可以跳转 if (![[UIApplication sharedApplication]canOpenURL:url]) { // 不能跳转就不要往下执行了 return; } if (@available(iOS 10.0, *)){ [[UIApplication sharedApplication]openURL:url options:@{UIApplicationOpenURLOptionsSourceApplicationKey:@YES} completionHandler:^(BOOL success) { if (success) { NSLog(@"10以后可以跳转url"); }else{ NSLog(@"10以后不可以跳转url"); } }]; }else{ BOOL success = [[UIApplication sharedApplication]openURL:url]; if (success) { NSLog(@"10以前可以跳转url"); }else{ NSLog(@"10以前不可以跳转url"); } }
Swift 版本:
let url = URL(string: "itms-apps://itunes.apple.com/app/id1129144823") // 注意: 跳转之前, 可以使用 canOpenURL: 判断是否可以跳转 if !UIApplication.shared.canOpenURL(url!) { // 不能跳转就不要往下执行了 return } if #available(iOS 10.0, *) { UIApplication.shared.open(url!, options: [:]) { (success) in if (success) { print("10以后可以跳转url") }else{ print("10以后不能完成跳转") } } } else { // Fallback on earlier versions let success = UIApplication.shared.openURL(url!) if (success) { print("10以下可以跳转") }else{ print("10以下不能完成跳转") } }
-
<2>、打电话:
tel://电话号码
,代码和上面的一样 -
<3>、发短信:
sms://电话号码
,代码和上面的一样 -
<4>、发邮件:
mailTo://邮箱号
,代码和上面的一样
提示:
itms-apps、https、tel、sms、mailTo
都是协议,app之间跳转的协议是:Scheme
,如果想要跳转到不同app,就要打开对应的 URL(协议是:scheme
), scheme是一个具体的字符串,并不是scheme这几个字母,在下面会详细的介绍 -
-
1.3、
URL
: 统一资源定位符-
<1>、我们以淘宝网的一个链接为例:
https://www.taobao.com/markets/bao/xiangbao?spm=a21bo.2017.201867-main.5.5af911d9blzLlJ
Swift版本let url = URL(string: "https://www.taobao.com/markets/bao/xiangbao?spm=a21bo.2017.201867-main.5.5af911d9blzLlJ") print("协议=",url!.scheme ?? "","IP或者是域名=",url!.host ?? "","路径=",url!.path ,"参数=",url!.query ?? "")
打印结果:
协议= https IP或者是域名= www.taobao.com 路径= /markets/bao/xiangbao 参数= spm=a21bo.2017.201867-main.5.5af911d9blzLlJ
OC版本NSURL *url = [NSURL URLWithString:@"https://www.taobao.com/markets/bao/xiangbao?spm=a21bo.2017.201867-main.5.5af911d9blzLlJ"]; NSLog(@"协议=%@ IP或者是域名=%@ 路径=%@ 参数=%@",url.scheme,url.host,url.path,url.query);
打印结果和上面的一样
-
<2>、一个
url
分为以下部分协议:https IP或者是域名:www.taobao.com 路径:/markets/bao/xiangbao 参数:spm=a21bo.2017.201867-main.5.5af911d9blzLlJ
-
二、应用间跳转实现
-
2.1、我们先以自己创建的app实现来回的跳转:
Test1
与Test2
两个项目 -
2.2、给Test2项目设置一个
给Test2项目设置一个 `URL Scheme`,用来其他的app跳转到 `Test2`URL Scheme
,用来其他的app跳转到Test2
提示:设置 URL Scheme时, 不要加
://
,比如上面直接设置:test2
一个字符串就好- 再说一下不一定根据
URL Scheme
进入不同的界面的,也可以在Scheme后拼接参数,比如:test2://1234
-
URL scheme
的作用:我们可以将应用“绑定”到一个自定义URL scheme
上,该scheme
用于从浏览器或其他应用中启动本应用,同时跳转时也可以传递参数。比如,可以在网页上添加一个链接,点击这个链接后会自动打开对应的APP上。或者从一个 APP 跳转到另一个 APP,用的也是URL scheme
。比如微博或者微信的登录或者分享之类的。在选择登录时就会跳到微信或者微博里,等登录了以后就可以跳转回去。
- 再说一下不一定根据
-
2.3、在Test1项目里面设置白名单
-
<1>、解释一下什么是白名单:其实白名单是在
iOS9.0
以后提出的,它就是一个数组
,里面放的是其他app的URL Scheme
名字,在iOS9以前
是不需要设置的,可以直接用canOpenURL
判断是否可以跳转,但是在iOS9.0之后如果不添加白名单,openURL
是无法判断判断是否可以跳转的。提示:不想添加白名单是可以的,其他的app分享到微信,它确信你的app存在,就不需要在白名单添其他app的
URL Scheme
,也就是不需要使用 canOpenURL判断是否可以跳转 是否可以跳转 -
<2>、设置白名单,如果你要跳转其他的app,就要在自己的app的
白名单的设置info.plist
设置白名单,添加其他app的URL Scheme
,白名单的字段是:LSApplicationQueriesSchemes
,下面我们在Test1
添加白名单
-
-
2.4、在Test1项目跳转到Test2项目测试,代码如下
我们把上面 1.2中的<1>里面的url换为下面,在同一个手机上运行 Test1 和 Test2 两个项目
跳转效果-
OC 版本:后面的代码都是
1.2
中的<1>
里面的代码NSURL *url = [NSURL URLWithString:@"test2://"]; // 注意: 跳转之前, 可以使用 canOpenURL: 判断是否可以跳转 if (![[UIApplication sharedApplication]canOpenURL:url]) { // 不能跳转就不要往下执行了 return; } ------后面的代码都是 1.2中的<1>里面的代码
-
Swift 版本:后面的代码都是
1.2
中的<1>
里面的代码let url = URL(string: "test2://") // 注意: 跳转之前, 可以使用 canOpenURL: 判断是否可以 if !UIApplication.shared.canOpenURL(url!) { // 不能跳转就不要往下执行了 return } -----后面的代码都是 1.2中的<1>里面的代码
拓展:看到上面效果,我们就简单的完成了app之间的跳转,这也是一些三方在分享的时候要求我们app设置白名单,你要分享到哪些平台,你就要添加其他平台的 URL Scheme,这个不是随便填写的,其他平台设置的URL Scheme是什么,就在白名单就要添加什么,可不是自己随意写的
-
-
2.5、如果你想在
Test2
app再返回到Test1
app,其实也就是反过来,在Test2
的白名单里面添加Test1
的URL Scheme
,在跳转Test1
的使用根据Test1的schmem
用openURL返回,记得先用canOpenURL
判断一下提示:在做分享的时候我们会检测微信是不是安装了,跳到微信后把微信给的URL Scheme也带了过去,在从微信返回的时候不用再判断 自己的app是否安装了,直接用OpenURL返回即可,添加白名单的目的是为了检测其他的app是否安装,可不可以跳转;在自己的app跳转其他的app的一定要用canOpenURL检测一下,微信不在白名单添加其他app的URL Scheme的原因是它确信你的app存在,不需要用
canOpenURL
判断 -
2.6、常用白名单字段(更多的白名单字段在mob平台iOS开发文档查看)
-
新浪
sinaweibo, sinaweibohd, sinaweibosso, sinaweibohdsso, weibosdk, weibosdk2.5
-
微信
wechat, weixin
-
支付宝
alipay, alipayshare
-
QQ
mqqOpensdkSSoLogin, mqqopensdkapiV2, mqqopensdkapiV3, wtloginmqq2, mqq, mqqapi timapi
提示:微信,新浪,QQ它们设置很多的Scheme的原因是要根据这些不同的Scheme做什么操作,比如根据
Scheme
跳转到不同的界面等等 -
三、怎样跳转到不同界面?
-
3.1、再建立一个项目
再建立一个项目Test3,给它添加一个Url SchemeTest3
,给它添加一个URL Scheme
,再给Test3添加两个控制器ViewController2
与ViewController3
提示: 一个项目可以添加多个
URL Scheme
,举个例子,你在用支付宝支付,支付宝会给你一个URL Scheme
字符串,让你添加到自己URL Types
里面,到时候你在调用支付宝支付,在支付宝界面返回的时候用这个支付宝给你的 URL Scheme 返回;同样,微信也会给你一个URL Scheme
字符串,当你跳转到微信里面,微信里面根据微信给你的URL Scheme
返回到你的app;- 再解释一下:为什么微信或者支付宝会给一个唯一的
URL Scheme
字符串,其目的是为了防止,从他们的应用返回到自己的应用时出错,根据URL Scheme
字符串返回到自己的app的,如果手机里面有两个程序都有相同的一个URL Scheme
字符串,那么就出问题了,它就不知道返回哪个app了,其实如果遇到相同的URL Scheme
,谁的app先安装的,就返回到谁的app,这个我测试了
- 再解释一下:为什么微信或者支付宝会给一个唯一的
-
3.2、在
Test3
处理其他Test1(或者其他的app通过openURL
)进来的判断- OC 版本
// 即将过期,不建议使用(建议把这3个方法同时实现) - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { [self dealopenURL:url]; return YES; } -(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{ [self dealopenURL:url]; return YES; } -(void)dealopenURL:(NSURL *)url{ NSLog(@"协议=%@ IP或者是域名=%@ 路径=%@ 参数=%@",url.scheme,url.host,url.path,url.query); // 1.获取主控制器 UINavigationController *rootNav = (UINavigationController *)self.window.rootViewController; // 拿到栈底的控制器 ViewController *mainVc = [rootNav.childViewControllers firstObject]; // 返回主控制器,防止多次进入错乱 [rootNav popToRootViewControllerAnimated:NO]; // 利用 URL : 统一资源定位符来判断 if ([url.path isEqualToString:@"/vc2"]) { ViewController2 *vc2 = [ViewController2 new]; vc2.urlString = url.host; [mainVc.navigationController pushViewController:vc2 animated:YES]; } else if ([url.path isEqualToString:@"/vc3"]) { ViewController3 *vc3 = [ViewController3 new]; vc3.urlString = url.host; [mainVc.navigationController pushViewController:vc3 animated:YES]; } }
-
Swift 版本
// 最新的 func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { dealopenURL(url: url as NSURL) return true } // 被遗弃的(最好两个都用) func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { dealopenURL(url: url as NSURL) return true } // MARK:跳转的处理 func dealopenURL(url:NSURL){ let nav: UINavigationController! = window?.rootViewController as? UINavigationController nav.popToRootViewController(animated: false) let rootVC = nav.children[0] if url.path == "/vc2" { let vc2 = ViewController2() vc2.urlString = url.host rootVC.navigationController?.pushViewController(vc2, animated: true) }else if url.path == "/vc3"{ let vc3 = ViewController3() vc3.urlString = url.host rootVC.navigationController?.pushViewController(vc3, animated: true) } }
提示:上面跳转是利用 URL的path(
统一资源定位符
)来判断,我是把 带过来的URL Scheme
放到了IP或者是域名
的位置 -
3.3、在
Test1
里面的跳转代码- OC 版本
// 跳转Test3的ViewController2 [self jumpUrl:@"test3://test1/vc2"]; // 跳转Test3的ViewController3 [self jumpUrl:@"test3://test1/vc3"]; -(void)jumpUrl:(NSString *)urlStr{ NSURL *url = [NSURL URLWithString:urlStr]; // 注意: 跳转之前, 可以使用 canOpenURL: 判断是否可以跳转 if (![[UIApplication sharedApplication]canOpenURL:url]) { return; } if (@available(iOS 10.0, *)){ [[UIApplication sharedApplication]openURL:url options:@{UIApplicationOpenURLOptionsSourceApplicationKey:@YES} completionHandler:^(BOOL success) { if (success) { NSLog(@"10以后可以跳转url"); }else{ NSLog(@"10以后不可以跳转url"); } }]; }else{ BOOL success = [[UIApplication sharedApplication]openURL:url]; if (success) { NSLog(@"10以前可以跳转url"); }else{ NSLog(@"10以前不可以跳转url"); } } }
-
Swift 版本
jumpUrl(url: NSURL(string: "test3://test1/vc2")!) jumpUrl(url: NSURL(string: "test3://test1/vc3")!) func jumpUrl(url:NSURL){ if !UIApplication.shared.canOpenURL(url as URL) { return } if #available(iOS 10.0, *) { UIApplication.shared.open(url as URL, options: [:]) { (success) in if (success) { print("10以后可以跳转url") }else{ print("10以后不能完成跳转") } } } else { // Fallback on earlier versions let success = UIApplication.shared.openURL(url as URL) if (success) { print("10以下可以跳转") }else{ print("10以下不能完成跳转") } } }
四、总结
-
4.1、实现两个app之间跳转的步骤
- <1>、在各自的app里面设置
URL scheme
- <2>、在各自app的info.plist里面添加字段
LSApplicationQueriesSchemes
,类型为数组,数组中添加对方的 scheme 字符串(白名单的作用仅仅是iOS9.0方法canOpenURL
要求的,因为我们在跳转前需要检查下设备有没有安装将要跳转的应用) - <3>、通过
openURL
跳转对方的URL Scheme
即可
- <1>、在各自的app里面设置
-
4.2、在最后我重复一下很多app跳转到微信、支付宝、微博等等后,它们是怎么做到再回到我们的app的,首先我们知道这些app里面的白名单肯定是没有我们的
URL Scheme
答:首选我们在其他平台注册自己的应用的时候,都会给我们一个 URL Scheme 字符串,这个字符串我们需要添加到我们的URL Scheme里面
,想必大家也知道了,我们需要添加多个URL Scheme
,因为微博,微信,支付宝都会给我们一个唯一的URL Scheme
字符串,唯一是为了防止我们跳转到他们的app后再返回的时候出错,还有其他设备的URL Scheme
与我们的一样就会造成返回错乱的情况;再说支付宝微信在返回我们的app的时候他们不去白名单里面添加我们的URL Scheme
,那是因为他们知道我们的设备肯定有我们的app,不然怎么会进入到微信和支付宝的?又有人说了我先进到微信,在弹出返回自己app和留在微信的界面弹出,我进入后台去把自己的app卸载,再去微信点击返回自己的app,其实我也是这么测试的,但是只要离开微信,返回自己app和留在微信的按钮就会消失,所以微信返回其他的app是不需要在白名单添加其他app的URL Scheme
。