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实现来回的跳转:Test1Test2 两个项目

  • 2.2、给Test2项目设置一个 URL Scheme,用来其他的app跳转到 Test2

    给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、如果你想在Test2app再返回到Test1app,其实也就是反过来,在 Test2 的白名单里面添加Test1URL 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 Scheme,再给Test3添加两个控制器 ViewController2ViewController3

    再建立一个项目Test3,给它添加一个Url Scheme

    提示: 一个项目可以添加多个 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 即可
  • 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

测试的demo

到此结束这篇文章,希望你能够通过这篇博客彻底知道 URL Scheme作用和白名单是什么以及如何在app之间跳转。有不理解的地方写下你的评论,看到后我会第一时间回答。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容