iOS App间常用的通信方式

背景:目前公司维护2个App,一个电商类项目,一个金融类项目;类似淘宝和支付宝,很多时候需要在App之间进行通信,多次使用以后,查阅相关资料,记录相关信息,文章所描述的内容如一下列表

  1. App间常用的通信方式
  2. 各种方式的优缺点
URL Scheme

做iOS开发的都应该知道,苹果选择沙盒的方式来保障用户的隐私和安全,App只能访问自己的沙盒,同事禁止其他非系统的应用访问App沙盒,大概意思就是,只有自己才能访问自己的沙盒(苹果系统除外)。因此苹果需要提供了一个或多个可以在App之间跳转的方法:URL Scheme就是其中一种。如果你的App有被别的App访问的功能或者数据,那么你必须在你的App定义一个相对应的URL Scheme,这就是访问你App的桥梁。当别的App使用一个URL Scheme进行访问时,系统会根据URL Scheme进行匹配,执行相应的操作。

优点
  1. 这种跳转方式是很灵活的,只需要在.plist文件里面做简单的处理,然后本地只需要需要进行简单逻辑处理,也可以用使用openURL来打开App对应的控制器,而这个你想要打开的URL Scheme是可以动态的从服务器动态获取的。那么这样就很简单的实现了动态跳转。
  2. URL Scheme传递参数的方式也与URL一致,只需要简单的在URL里附加上对应的参数即可。
  3. 这种页面跳转是无差别的,通过URL Scheme跳转可以无缝的在H5页面和原生页面之间跳转传值,而无非做更多的逻辑判断。
缺点
  1. 写在info.plist文件中的Scheme可能会被一些反编译手段获取到。
  2. URL Scheme可能会被劫持调来安全隐患
建议
  1. 苹果可以限制 iOS 应用不能注册别的应用的 Bundle ID 作为 URL Scheme。这样的话,使用自己的 Bundle ID 作为 URL Scheme 的接收器就会变的安全很多。

  2. 第三方应用可以通过①给自己发送 URL Scheme 请求来证明没有被劫持,如果没有收到自己的 URL Scheme,就可以及时给用户发送提醒;②利用 MobileCoreServices 服务中的 applicationsAvailableForHandlingURLScheme() 来查看所有注册了该 URL Schemes 的应用和处理顺序,从而检测自己、或者别人的 URL Scheme 是否被劫持。

Keychain

iOS系统的Keychain是一个安全的存储容器,它本质上就是一个sqllite数据库,它的位置存储在/private/var/Keychains/keychain-2.db,不过它所保存的所有数据都是经过加密的,可以用来为不同的app保存敏感信息,比如用户名,密码等。iOS系统自己也用keychain来保存VPN凭证和Wi-Fi密码。它是独立于每个App的沙盒之外的,所以即使App被删除之后,Keychain里面的信息依然存在。
基于安全和独立于app沙盒的两个特性,Keychain主要用于给app保存登录和身份凭证等敏感信息,这样只要用户登录过,即使用户删除了app重新安装也不需要重新登录。
那Keychain用于App间通信的一个典型场景也和app的登录相关,就是统一账户登录平台。使用同一个账号平台的多个app,只要其中一个app用户进行了登录,其他app就可以实现自动登录不需要用户多次输入账号和密码。一般开放平台都会提供登录SDK,在这个SDK内部就可以把登录相关的信息都写到keychain中,这样如果多个app都集成了这个SDK,那么就可以实现统一账户登录了。
Keychain的使用比较简单,使用iOS系统提供的类KeychainItemWrapper,并通过keychain access groups就可以在应用之间共享keychain中的数据的数据了

优缺点
  1. 数据并不存放在App的Sanbox中,即使删除了App,资料依然保存在keychain中。如果重新安装了app,还可以从keychain获取数据。
  2. keychain的数据可以用过group方式,让程序可以在App间共享。不过得要相同TeamID
  3. keychain的数据是经过加密的
UIPasteboard

在iOS的UI系统中,有3个控件自带剪切板操作,分别是UITextField、UITextView与UIWebView。在这些控件的文字交互处进行长按手势可以在屏幕视图上唤出系统的剪切板控件,用户可以进行复制、粘贴,剪切等操作

UIPasteboard典型的使用场景就是淘宝跟微信/QQ的链接分享。由于腾讯和阿里的公司战略,腾讯在微信和qq中都屏蔽了淘宝的链接。那如果淘宝用户想通过QQ或者微信跟好友分享某个淘宝商品,怎么办呢? 阿里的工程师就巧妙的利用剪贴板实现了这个功能。首先淘宝app中将链接自定义成淘口令,引导用户进行复制,并去QQ好友对话中粘贴。然后QQ好友收到消息后再打开自己的淘宝app,淘宝app每次从后台切到前台时,就会检查系统剪切板中是否有淘口令,如果有淘口令就进行解析并跳转到对于的商品页面

去年面试蚂蚁金服的时候还被问到这个问题,当时只是回到了了前面的URL Scheme和Keychain,现在终于有机会做一次这方面的只是整理,弥补自己在知识储备方面的不足。

优点

通用性,只要需要识别特定的标识,可以不受APP之间通信的影响

缺点

需要用户手动处理

UIDocumentInteractionController

由于沙盒的严格限制,导致程序之间共享数据比较麻烦。一般在程序间共享文档可以通过UIDocumentInteractionController类实现通讯。它支持在你的app中用其他app预览和显示文档。同时也支持文件关联,允许其他app通过你的程序打开文件。这些技术包括了UIKit中提供的UIDocumentInteractionController类(UIDocumentInteractionController Class Reference),以及Quick Look框架(Quick Look Framework Reference)。

如果你的app需要打开它不支持的文件(PDF文件、图像文件,等等),或者需要将app的文件传输给另外一个允许接收此类型文件的app时。可以使用文件交互控制器(UIDocumentInteractionController类的实例)为用户提供可接收程序来处理文件,说的简单点就是通过Quick Look框架判断文档是否能被另一个app打开和预览。目前我们公司的文档处理就是通过这来解决的。

//创建实例
NSURL *filePath = [NSURL fileURLWithPath:path];
UIDocumentInteractionController *documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]];
//显示窗口
BOOL b = [documentController presentPreviewAnimated:YES];
local socket

这种我是提一次听说,是翻阅了好多资料后才看到的,完全陌生。

这种方式不太常见,也是很容易被iOS开发者所忽略但是特别实用的一种方法。它的原理很简单,一个App1在本地的端口port1234进行TCP的bind和listen,另外一个App2在同一个端口port1234发起TCP的connect连接,这样就可以建立正常的TCP连接,进行TCP通信了,那么就想传什么数据就可以传什么数据了。
这种方式最大的特点就是灵活,只要连接保持着,随时都可以传任何相传的数据,而且带宽足够大。它的缺点就是因为iOS系统在任意时刻只有一个app在前台运行,那么就要通信的另外一方具备在后台运行的权限,像导航或者音乐类app。
它是常用使用场景就是某个App1具有特殊的能力,比如能够跟硬件进行通信,在硬件上处理相关数据。而App2则没有这个能力,但是它能给App1提供相关的数据,这样APP2跟App1建立本地socket连接,传输数据到App1,然后App1在把数据传给硬件进行处理。

参考资料

http://www.cocoachina.com/ios/20171229/21709.html
https://www.25pp.com/news/news_71805.html
https://www.jianshu.com/p/d3185c70cc44
https://www.jianshu.com/p/bf6b42470bba
https://developer.apple.com/documentation/uikit/uidocumentinteractioncontroller

推荐阅读更多精彩内容