美文网首页iOS开发iOS_UIkit[0001]iOS实用笔记
iOS开发--一步步教你彻底学会『iOS应用间相互跳转』

iOS开发--一步步教你彻底学会『iOS应用间相互跳转』

作者: ITCharge | 来源:发表于2016-09-14 22:50 被阅读6479次

    本文首发于我的个人博客:『不羁阁』 https://bujige.net
    文章链接:https://bujige.net/blog/iOS-Application-jump.html

    这篇文章通过一步步指导,教你彻底学会『iOS应用间相互跳转』问题。文末有Github的学习Demo。

    1. 应用间相互跳转简介

    在iOS开发的过程中,我们经常会遇到需要从一个应用程序A跳转到另一个应用程序B的场景。这就需要我们掌握iOS应用程序之间的相互跳转知识。

    下面来看看我们在开发过程中遇到的应用场景。

    2. 应用间相互跳转应用场景

    1. 使用第三方用户登录,跳转到需授权的App。如QQ登录,微信登录等。
      • 需要用户授权,还需要"返回到调用的程序,同时返回授权的用户名、密码"。
    2. 应用程序推广,跳转到另一个应用程序(本机已经安装),或者跳转到iTunes并显示应用程序下载页面(本机没有安装)。
    3. 第三方支付,跳转到第三方支付App,如支付宝支付,微信支付。
    4. 内容分享,跳转到分享App的对应页面,如分享给微信好友、分享给微信朋友圈、分享到微博。
    5. 显示位置、地图导航,跳转到地图应用。
    6. 使用系统内置程序,跳转到打电话、发短信、发邮件、Safari打开网页等内置App中。

    那么我们如何实现应用间的相互跳转呢?先来看下原理。

    3. 应用间相互跳转实现原理

    在iOS中打开一个应用程序只需要拿到这个应用程序的协议头即可,所以我们只需配置应用程序的协议头即可。

    假设有应用A应用B两个应用,现在需要从应用A跳转到应用B中。

    • 原理:通过设置跳转到应用B的URL Schemes(自定义的协议头),应用B将其自身“绑定”到一个自定义URL Schemes上,就可以从应用A中利用应用B的URL Schemes启动应用B了。

    具体怎么做呢,下面一步步来教你,先来个简单点的:从应用A跳转到应用B。

    4. 应用A跳转到应用B

    1. 首先我们用Xcode创建两个iOS应用程序项目,项目名称分别为App-A、App-B。
    2. 选择项目App-B -> TARGETS -> Info -> URL Types -> URL Schemes,设置App-B的URL Schemes为AppB。


      设置App-B的URL Schemes
    3. 在应用程序App-A中添加一个用来点击跳转的Button,并监听点击事件,添加跳转代码。


      添加跳转按钮
    - (IBAction)jumpToAppB:(id)sender {
        // 1.获取应用程序App-B的URL Scheme
        NSURL *appBUrl = [NSURL URLWithString:@"AppB://"];
    
        // 2.判断手机中是否安装了对应程序
        if ([[UIApplication sharedApplication] canOpenURL:appBUrl]) {
            // 3. 打开应用程序App-B
            [[UIApplication sharedApplication] openURL:appBUrl];
        } else {
            NSLog(@"没有安装");
        }
    }
    
    1. 如果是iOS9之前的模拟器或是真机,那么在相同的模拟器中先后运行App-B、App-A,点击按钮,就可以实现跳转了。

    2. 如果是iOS9之后的模拟器或是真机,那么则需要再在应用程序App-A中将App-B的URL Schemes添加到白名单中,原因和做法如下。

    • iOS9引入了白名单的概念。
    • 在iOS9中,如果使用 canOpenURL:方法,该方法所涉及到的 URL Schemes 必须在"Info.plist"中将它们列为白名单,否则不能使用。key叫做LSApplicationQueriesSchemes ,键值内容是对应应用程序的URL Schemes。

    具体做法就是在App-A的Info文件中,添加LSApplicationQueriesSchemes数组,然后添加键值为AppB的字符串。

    添加LSApplicationQueriesSchemes数组,然后添加键值为AppB的字符串

    添加白名单之后在相同的模拟器中先后运行App-B、App-A,点击按钮,就可以实现跳转了。

    具体效果如下图所示。

    App-A跳转到App-B

    下边学习以下从应用A跳转到应用B的特定界面。

    5. 应用A跳转到应用B的特定界面

    很多时候,我们做应用程序之间的跳转并不只是跳转到其他程序就可以了,而是要跳转到其他程序的特定页面上。比如我们在浏览网页时,会有分享到微信朋友圈或是分享给微信朋友,这就需要跳转到微信朋友圈界面或是微信朋友选择界面。

    具体如何做呢?

    1. 首先我们先来为App-B搭建两个页面Page1Page2。这里用导航控制器Push两个ViewController,通过Storyboard Segue设置两个ViewController的标识符绑定,分别为"homeToPage1"和"homeToPage2"。
    搭建两个页面`Page1`和`Page2` 设置Page1ViewController的标识符
    1. 在应用程序App-A中添加两个用来点击跳转的Button,一个跳转到Page1,一个跳转到Page2,并监听点击事件,添加跳转代码。
    添加两个跳转页面按钮
    - (IBAction)jumpToAppBPage1:(id)sender {
        // 1.获取应用程序App-B的Page1页面的URL
        NSURL *appBUrl = [NSURL URLWithString:@"AppB://Page1"];
    
        // 2.判断手机中是否安装了对应程序
        if ([[UIApplication sharedApplication] canOpenURL:appBUrl]) {
            // 3. 打开应用程序App-B的Page1页面
            [[UIApplication sharedApplication] openURL:appBUrl];
        } else {
            NSLog(@"没有安装");
        }
    }
    
    - (IBAction)jumpToAppBPage2:(id)sender {
        // 1.获取应用程序App-B的Page2页面的URL
        NSURL *appBUrl = [NSURL URLWithString:@"AppB://Page2"];
    
        // 2.判断手机中是否安装了对应程序
        if ([[UIApplication sharedApplication] canOpenURL:appBUrl]) {
            // 3. 打开应用程序App-B的Page2页面
            [[UIApplication sharedApplication] openURL:appBUrl];
        } else {
            NSLog(@"没有安装");
        }
    }
    

    3.在应用App-B中通过AppDelegate监听跳转,进行判断,执行不同页面的跳转

    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
    {
        // 1.获取导航栏控制器
        UINavigationController *rootNav = (UINavigationController *)self.window.rootViewController;
        // 2.获得主控制器
        ViewController *mainVc = [rootNav.childViewControllers firstObject];
    
        // 3.每次跳转前必须是在跟控制器(细节)
        [rootNav popToRootViewControllerAnimated:NO];   
    
        // 4.根据字符串关键字来跳转到不同页面
        if ([url.absoluteString containsString:@"Page1"]) { // 跳转到应用App-B的Page1页面
            // 根据segue标示进行跳转
            [mainVc performSegueWithIdentifier:@"homeToPage1" sender:nil];
        } else if ([url.absoluteString containsString:@"Page2"]) { // 跳转到应用App-B的Page2页面
            // 根据segue标示进行跳转
            [mainVc performSegueWithIdentifier:@"homeToPage2" sender:nil];
        }   
    
        return YES;
    }
    

    具体效果如下:

    App-A跳转到App-B的特定界面

    6.从应用B跳转回应用A

    1. 步骤分析:

    1. 我们想要从应用B再跳转回应用A,那么在跳转到应用B的时候,还应将应用A的URL Schemes传递过来。这样我们才能判断应该跳转回哪个应用程序。
    • 这样我们指定一个传递URL的规则:协议头://应用B的URL Schemes?应用A的URL Schemes。即:AppB://Page1?AppA
    • 说明:
      • AppB是跳转过来的应用App-B的URL Schemes;
      • Page1是用来区别跳转页面的标识;
      • ? 是分割符;
      • AppA是跳转回的应用App-A的URL Schemes
    1. 我们根据传递来的数据,进行反跳回去。
      1. 之前我们在应用App-B中通过AppDelegate执行不同页面的跳转。在对应方法中我们可以拿到完整的URL,在主控制器ViewController中设定一个属性,将该URL保存在主控制器中。
      2. 在主控制器中我们可以通过- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;方法获取将要跳转的页面控制器。
      3. 在将要跳转的页面控制器中定义一个属性,用于接受、截取出跳转回的应用(即App-A)的URL Schemes,执行跳转。

    2. 具体步骤:

    1. 准备步骤:
    1. 因为我们想要跳转回应用A,首先我们要先设置应用App-A的URL Schemes,将其设置为AppA。同时在应用App-B中添加白名单。具体操作和之前相似。
    2. 在App-B项目中的Page1和Page2两个页面各添加一个Button,用于跳转回App-A。同时添加Page1和Page2的页面控制器Page1ViewController和Page2ViewController。
    添加Page1和Page2的页面控制器Page1ViewController和Page2ViewController
    2. 实现步骤
    1. 在App-A中修改传递的URL。
    • 分别修改为:@"AppB://?AppA"@"AppB://Page1?AppA"@"AppB://Page2?AppA"
    1. 在App-B的主控制器ViewController中增加一条属性@property (nonatomic, copy) NSString *urlString;,并在App-B中通过AppDelegate中保存完整的URL。
    2. 在将要跳转的页面控制器Page1ViewController和Page2ViewController中定义一个属性@property (nonatomic, copy) NSString *urlString;,用于接受、截取出跳转回的应用(即App-A)的URL Schemes,执行跳转。
    3. 重写App-B的主控制器的- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender方法。
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        if ([segue.identifier isEqualToString:@"homeToPage1"]) {
            // 获得将要跳转的界面Page1的控制器
            Page1ViewController *Page1Vc = segue.destinationViewController;
            // 保存完整的App-A的URL给跳转界面Page1
            Page1Vc.urlString = self.urlString;
        } else if ([segue.identifier isEqualToString:@"homeToPage2"]) {
            // 获得将要跳转的界面Page2的控制器
            Page2ViewController *Page2Vc = segue.destinationViewController;
            // 保存完整的App-A的URL给跳转界面Page1
            Page2Vc.urlString = self.urlString;
        }
    }
    
    1. 在对应界面控制器Page1ViewController和Page2ViewController中实现跳转代码
      - Page1ViewController.m
    - (IBAction)page1BackToAppA:(id)sender {
        // 1.拿到对应应用程序的URL Scheme
        NSString *urlSchemeString = [[self.urlString componentsSeparatedByString:@"?"] lastObject];
        NSString *urlString = [urlSchemeString stringByAppendingString:@"://"];
    
        // 2.获取对应应用程序的URL
        NSURL *url = [NSURL URLWithString:urlString];
    
        // 3.判断是否可以打开
        if ([[UIApplication sharedApplication] canOpenURL:url]) {
            [[UIApplication sharedApplication] openURL:url];
        }
    }
    

    - Page2ViewController.m

    - (IBAction)page2BackToAppA:(id)sender {
        // 1.拿到对应应用程序的URL Scheme
        NSString *urlSchemeString = [[self.urlString componentsSeparatedByString:@"?"] lastObject];
        NSString *urlString = [urlSchemeString stringByAppendingString:@"://"];
    
        // 2.获取对应应用程序的URL
        NSURL *url = [NSURL URLWithString:urlString];
    
        // 3.判断是否可以打开
        if ([[UIApplication sharedApplication] canOpenURL:url]) {
            [[UIApplication sharedApplication] openURL:url];
        }
    }
    

    具体效果如下:

    App-B跳转回App-A

    还不太明白可参考下我的Github上Demo地址:YSC-AppAJumpToAppB

    相关文章

      网友评论

      • 0f4ac6f61ff0:我遇到一个问题就是:我有一个工程,然后我想创建不同的target来区分线上和测试环境的。但是我在手机上装完了两个target的应用,然后调用第三方的社交软件登录,返回来启动的target始终是同一个。

        简单来说就是同一个工程,两个target分别是A,B,两个共用所有资源。不同在于version号不同。然后我装了A,B到手机上,分别调用第三方登录,但都只会回调到A中。
      • 窝在北京玩泥巴:你好,请问为什么我跳转的时候没有弹出APP-A want to open App-B 的Alert弹框。
      • 鬼公子:写得很好,赞👍。不过应用A跳转应用B指定页面后,跳转回应用A没反应,下了您的demo,跳转回A这个功能也是没反应。不知什么问题?
      • yyggzc521:请问下,点击“状态栏左上角的返回App-A”有对应的事件触发么?
      • Reus丶你是我的梦想啊:你好,如果我需要跳转的是一个其他的应用程序,那我应该是去哪儿获取到该程序的URL Schemes呢,你这里好像就写了两个自己写的程序之间的相互跳转呢
        Reus丶你是我的梦想啊:@lesmiserables0 其实没有文档的话可以在iTunes下那个软件,然后拆包去看他的info.plist中是否有URL Schemes.:blush:
        lesmiserables0:比如你要跳微信或支付宝,就要去他们公开的接入文档里找URL Schemes,如果一个其他的应用程序不公开这个URL Schemes, 是无法跳到那个app的。
      • Bearger:请问下,点击“状态栏左上角的返回App-A”有对应的事件触发么?
      • sz流氓江: 问作者一个问题哈,就像我们调用微信一样,微信并没有把我们的app加进它的白名单,那它是怎么回调的我们的APP的呢?
        lesmiserables0:@洋洋洋xx 麻烦能详细讲解一下吗。对于微信的实现实在是很好奇。
        f36c399cabc1:你好,写的很好,转载下可以吗?标注名字,网址!!
        a217d1fd025f:应该使用的是通用链接
      • 陨之希留leo:实际开发中,如果我自己的app想要跳转到其他已经安装在手机里的app,比如京东、微信,那如何获取他们的协议头并写在自己工程里白名单和代码里呢?
      • 328b7047934f:请问如何想要跳转到 设置 > 数据流量 那一页怎么弄呢?(类似于launcher)page B 可以定于为设置里面的页面吗?
        ITCharge:@勇氣君 iOS10 有新的API。参考:https://github.com/sushushu/iOS10toSystemSetting
        - (BOOL)openURL:(NSURL*)url NS_DEPRECATED_IOS(2_0, 10_0, "Please use openURL:options:completionHandler: instead") NS_EXTENSION_UNAVAILABLE_IOS("");
        - (BOOL)canOpenURL:(NSURL *)url NS_AVAILABLE_IOS(3_0);
        // Options are specified in the section below for openURL options. An empty options dictionary will result in the same
        // behavior as the older openURL call, aside from the fact that this is asynchronous and calls the completion handler rather
        // than returning a result.
        // The completion handler is called on the main queue.
        - (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options completionHandler:(void (^ __nullable)(BOOL success))completion NS_AVAILABLE_IOS(10_0) NS_EXTENSION_UNAVAILABLE_IOS("");
        328b7047934f:@行走的少年郎 谢谢!还有就是现在iOS 10 把openurl给封了,建议博主可以提下~
        ITCharge:添加数据流量对应URL Schemes,然后按照文章里的步骤实现过程。
        这里有一个别人写的URL Schemes附录列表。你可以参考一下,
        https://github.com/cyanzhong/app-tutorials/blob/master/schemes.md
      • f5bfde00b550:请问下跳转指定页面是用的拖的方式 如果是纯代码跳转指定页面怎么绑定标识符,或者该怎么做呢
        ITCharge:@656797768 纯代码的话,需要将『5. 应用A跳转到应用B的特定界面』章节里的『 3.在应用App-B中通过AppDelegate监听跳转,进行判断,执行不同页面的跳转』这一步骤下手。
        和文章中描述的差不多,在App-B中的AppDelegate方法中openURL方法中:
        // 4.根据字符串关键字来跳转到不同页面" 将这部分变为纯代码的跳转即可。
        大致就是:创建不同页面的控制器,然后从主控制器中push进去。 只不过这里用的纯代码方式,而不是用的storyboard的绑定标识符。
      • 863c73f31933:你好,楼主,我这边定义了之后不跳转是怎么回事?
        863c73f31933:@行走的少年郎 嗯嗯找到原因了,是URL type写反了,工程里面的URL type应该写自己的,我这边写成要跳转的工程了,结果没跳转成功
        ITCharge:@SunlightInMyLif 看看步骤是不是错了?或是哪里写错了
      • Liusr:学习了,谢谢楼主!
        请问下,如何用微信扫码打开自己写的app?能实现吗
      • 抚明月兮长歌:请问一下,怎么判断我要跳转的app?我现在要跳转,怎么知道我要跳转的是微信还是支付宝?
        ITCharge:@黄昏的旅者 对微信跳转回原APP不是太了解,见网上有人说微信屏蔽了url scheme直接跳转,好像还有其他方法,不是太了解。而支付宝支付SDK里边,支付方法中可以传给支付宝服务器自己URLScheme,然后在支付结果的回调方法中,可以根据URLScheme,跳转回自己的客户端。
        具体可参考支付宝官方SDK https://doc.open.alipay.com/docs/doc.htm?treeId=59&articleId=103660&docType=1
        抚明月兮长歌:@行走的少年郎 跳转的时候并不执行handleOpenURL:只有回调的时候才执行,跳转的时候怎么才能拿到呢,在什么方法中?
        ITCharge:@黄昏的旅者 微信和支付宝都有自己的URL Schemes,在跳转的时候判断下就知道要跳转的是哪个APP了
      • 大好河山_:大神您好!我想请问下你,从appA跳转到appB,appB的URL Schemes协议头您怎么绑定的???请指教一下,谢谢
        ITCharge:@大好河山_ 不客气
        大好河山_:@行走的少年郎 谢谢您的回答,看懂了
        ITCharge:@大好河山_ 就是文章中 4. 应用A跳转到应用B 里边写的那样绑定的,你再看看,看还有什么不明白的没。
      • minjing_lin:点赞
        ITCharge:@MinJing_Lin :smile:谢谢支持哈
      • ad6d7cad1c03:谢谢分享,写的很详细。
        ITCharge:@暮从碧山下 不客气,有帮助就好。:smile:
      • 崠崠:ios9不是提供了返回的功能吗?就是右上角那个按钮?
        ITCharge:@崠崠 没有吧,我刚才又测试了一下,iOS10里也能跳转到 application openURL 的函数里边。你先在 APP-B 的 application openURL 函数中打个断点,然后先运行APP-B,再运行APP-A试一下看看。
        ITCharge:@崠崠 恩,不过有些场景需要自己来做返回原有App的跳转,比如说第三方支付。
      • 484eb8f59879:你好,像微信支付那样或分享那样,并没有设置其他应用URLScheme,为什么也能返回到跳转到微信之前的应用??
        ITCharge:@SmileLiusr 我刚刚查看了支付宝SDK,支付方法中可以传给支付宝服务器自己URLScheme,然后在支付结果的回调方法中,可以根据URLScheme,跳转回自己的客户端。
        具体可参考支付宝官方SDK https://doc.open.alipay.com/docs/doc.htm?treeId=59&articleId=103660&docType=1
        ITCharge:@484eb8f59879 我刚刚查看了支付宝SDK,支付方法中可以传给支付宝服务器自己URLScheme,然后在支付结果的回调方法中,可以根据URLScheme,跳转回自己的客户端。
        具体可参考支付宝官方SDK https://doc.open.alipay.com/docs/doc.htm?treeId=59&articleId=103660&docType=1
        Liusr:@484eb8f59879 同问
      • 十一岁的加重:学习了,
      • Pusswzy:写的很好 有几个问题想请教你
        绑定URL Schemes的意思 是APP A 绑定的是APP A, APP B绑定的是APP B.
        但是在白名单中确实相反的APP A 填写B的白名单?
        Pusswzy:@行走的少年郎 明白了 十分感谢你详细的回复
        ITCharge:@Pusswzy
        是的,APP A 的URL Schemes绑定的是APP A, APP B的URL Schemes绑定的是APP B.
        而白名单却是相反设置的。可以这样理解:如果你的应用A想要访问应用B,就必须在应用A的白名单中加入应用B,表示允许应用A访问应用B。
        换个场景可以这样想:例如打电话,假设所有号码在你手机里默认都是黑名单,你想要打电话给138XXXXXXX,那么就要在你的手机里的白名单里边加上138XXXXXXX,你的手机才允许打电话给138XXXXXXX。
      • 春泥Fu:很详细~
        ITCharge:@春泥Fu :smile:谢谢

      本文标题:iOS开发--一步步教你彻底学会『iOS应用间相互跳转』

      本文链接:https://www.haomeiwen.com/subject/nozvettx.html