本篇博客就先封装一个LoginSDK, 让后将该SDK植入到两个App中(一个暂且叫作“App One”, 另外一个暂且称为“App Two”)。当App One登陆成功后,当你在打开App Tow进行登陆时,咱们封装的LoginSDK会从KeyChain中取出App One的帐号进行登陆。前提是这两个App设置了Keychain Share。废话少说,进入今天的主题。html
1、功能总述git
在博客开始的第一部分,咱们先来看一下咱们最终要实现的效果。下图中所表述的就是咱们今天博客中要作的事情,下方的App One和App Two都植入了咱们将要封装的LoginSDK, 两个App中都设置了Keychain Share。当App One经过咱们的LoginSDK登陆后,在启动App Two时,会去检索是否有帐号以及在分享的Keychain中存储了,若是有的话,那么不会弹出“登陆”界面,直接进行隐式登陆。固然上述这些工做都是在咱们的LoginSDK中进行作的事情。github
本部分算是本篇博客的一个综述吧,从下方截图中,咱们能清楚的看到上述的两个App中都植入了咱们接下来要封装的SDK。LoginSDK.framework就是咱们封装的登陆静态库,其中提供了用户所调用的API。面试
下方这个截图中的内容就是用户所调用LoginSDK的API。由于咱们作的只是一个Demo,因此下方的API接口比较简单,若是你要和现实App中真正的需求和业务逻辑整合到一块,那么封装一个登陆用的SDK是很是麻烦的。由于我考虑过把咱们团队所开发的几个App中的登陆模块封装成SDK, 仔细考虑了一下,东西仍是蛮多的。扯远了,不过今天这个Demo仍是能够提供一个大致思路的。bash
下方API的对象是经过单例来获取的,若是是首次登陆的话,就须要调用getLoginViewController这个方法来获取登陆页面,而且这个函数须要提供一个Block参数,这个Block参数用来处理登陆成功后的事件。而登陆失败等事件就在咱们SDK中自行处理了。微信
checkHaveLogin方法是用来检查是否已经有帐号登陆过,该方法须要提供两个Block,一个是登陆成功要执行的Block,一个是没有已登陆帐号时执行的Block。当执行该方法时,若是以前有帐号登陆过的话,就直接进行隐式登陆,登陆成功后执行loginSuccessBlock。以前若是没有帐号在此设备上登陆就执行noAccountBlock, 来处理首次登陆的事件。函数
该部分先聊这么多,接下来会根据上述的知识点详细的展开。oop
2、LoginSDK的封装测试
在封装LoginSDK以前呢,SDK的源代码以及所依赖的资源得准备好对吧。下方截图就是咱们LoginSDK的源代码,下方绿框中的部分是留给用户使用的API, 而黄框中的部分就是咱们这个SDK所依赖的资源了,虽然此处只用一个Storyboard,咱们仍是有必要将该资源文件打包成Bundle文件提供给用户的。而其余源代码SDK的用户是看不到的。源码准备好,测试完毕后,接下来咱们就要进行SDK的封装了。微信支付
1.建立iOS Framework工程
首先咱们须要建立一个iOS的CocoaTouch工程,点击Next,输入咱们Framework的名字便可。下方咱们暂且将该Framework的名字命名为“CreateLoginSDKFramework”。以下所示:
2.设定兼容版本
建立完工程后,咱们要选择“Deployment Target”, 此处咱们选择的是8.0。也就是说此处咱们封装的SDK所支持的iOS系统版本是iOS8.0+。
3.选择“静态库”
咱们建立的framework默认是动态库,因此咱们要讲Mach-O Type设置为静态库“Static Library”,以下所示。
4.引入源代码并进行编译
配置好上述选项后,接下来咱们就须要将咱们事先准备好的SDK源代码引入到咱们的Framework的工程中进行编译了,在编译以前咱们要选择SDK用户能够看到的文件。下方截图中就是在Build Phases下的Headers中进行设置的。将用户能够看到的头文件房子Public中,用户看不到的放在Project中。以下所示。
5.编译
上述设置和配置完毕后,咱们就要对咱们的Framework工程进行编译了。先选择模拟器进行编译,而后选择真机进行编译。编译完后,在Products下会生成相应的Framework, 而后经过Show in Finder进行查看便可。查看时,若是想看“模拟器”和“真机”的framework的话,在Show in finder后,须要前往上层文件夹查看。具体以下所示。
6.Framework的合并
由于在模拟器下编译会生成模拟器下使用的Framework,在真机下编译会生成真机使用的Framework。若是想咱们生成的Framework既能够在真机下使用,也能够在模拟器下使用,那么咱们须要将两个Framework进行合并。
下方截图中,这两个framework一个是真机生成的,另外一个是模拟器生成的,咱们作的事情就是将下方绿框中的两个文件进行合并。而后使用合并后的文件将下方的文件替换便可。替换后的framework就能够在模拟器和真机下进行使用了。
咱们使用“lipo -create 模拟器framework路径 真机framework路径 -output 新的文件”命令将上述两个文件进行合并。下方就是合并上述两个文件的执行命令, 执行完下方命令后会生成合并后的文件,将上述文件进行替换便可。通过上述步骤,咱们的Framework至此就封装完毕了。
3、封装Bundle
封装完Framework后,接下来咱们要对Framework依赖的资源文件进行打包了。由于咱们SDK中的界面是使用Storyboard作的,因此须要将Storyboard打包成Bundle资源文件与上述的Framework一块儿使用。若是咱们SDK中须要一些图片资源的话,也能够进行一并打包。接下来咱们就要对资源文件进行打包。
1.Bundle工程的建立
首先咱们像建立Framework工程同样建立一个Bundle工程,由于iOS工程下方没有Bundle类型的工程,因此咱们须要在OS X -> Framework & Library -> Bundle下面来建立咱们的Bundle工程。选择完后,输出咱们的Bundle文件的名称便可,以下所示:
2. Bundle工程的配置
建立完Bundle工程后,咱们要对其进行相应的配置。由于咱们是选择OS X建立的Bundle,默认的Bundle是不能在iOS中使用的,因此咱们得将Base SDK进行设置,选择相应的iOS版本便可,以下所示。选择完Base SDK后,咱们还要像上面Framework的封装同样,设置一下要兼容的iOS版本(iOS Deployment Target), 在此就不作过多赘述了。
3.引入资源,进行编译
进行上述配置完后,接下来就是引入资源文件进行编译了,下方引入的资源文件就是咱们的LoginSDK.storyboard。引入资源后,进行编译,编译后会在Products下面生成相应的Bundle资源文件,该文件就能够和咱们的Framework进行使用了。
4.Bundle资源的加载
生成完Bundle资源文件后,咱们在SDK的源代码中,要从Bundle资源文件中进行资源的加载。下方代码就是加载相应Bundle的代码。经过下方的宏定义,就能够经过“Bundle”的名字来加载Bundle。下方的LOGIN_SDK_BUNDLE就是咱们要使用的Bundle资源文件的对象。
#define LOGIN_SDK_BUNDLE_NAME @"LoginSDKResource.bundle"
#define LOGIN_SDK_BUNDLE_PATH [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: LOGIN_SDK_BUNDLE_NAME]
#define LOGIN_SDK_BUNDLE [NSBundle bundleWithPath: LOGIN_SDK_BUNDLE_PATH]
复制代码
下方代码就是从上述Bundle对象中加载相应的Storyboard。与咱们以前的代码不一样,以前咱们是从MainBundle中加载的Storyboard,而如今咱们是从指定的Bundle中来加载Storyboard。具体代码以下所示。
4、SDK的引入
SDK已经依赖的资源文件封装完毕后,接下来就是在其余App中使用了。在第一部分中的App One和App Two都引入了上述咱们封装的LoginSDK。引入SDK步骤也是比较简单的,这和引入友盟,个推,微信支付,支付宝等等SDK的步骤差很少。下方就是咱们引入SDK的步骤。
1.导入SDK并进行相关配置
导入SDK到咱们的App工程后,咱们要对其进行相应的配置。首先咱们要对Framework Search Paths进行配置,也就是说告诉编译器咱们的第三方SDK所在的位置。下方这个配置项在引入SDK后就默认存在的,若是没有的话就进行配置便可。
配置完路径后,接下来咱们要在Other Linker Flags添加上-Objc和-all_load选项。这两个选项在以前的博客中也不止一次的提到过。-Objc这个flag告诉连接器把库中定义的Objective-C类和Category都加载进来。而-all_load会强制连接器把目标文件都加载进来,即便没有objc代码。根据上面介绍的,下方即便不添加-Objc这个选项,下方的工程也是能够正常运行的。
2.SDK的使用
配置完毕后,接下来就是在咱们App中使用该SDK了。下方代码就是咱们上述LoginSDK的使用方式,首先获取单例,而后检查是否登陆,登陆成功后根据Block回调跳转到首页,若是未登陆,就经过LoginAPI获取登陆页面进行登陆。具体以下所示。
5、Keychain共享
关于Keychain共享的东西,咱们能够看一下上一篇博客的介绍《iOS逆向工程之KeyChain与Snoop-it》。而在本篇博客中,是对keychain共享的应用,在植入上述LoginSDK后,若是想多个App间进行帐号共享的话,要在相应的App上添加Keychain Share的标示了。下方截图就是咱们第一部分那两个App中所设置的Keychain共享的配置项了。具体以下所示。
通过上面的全部步骤,咱们封装了一个简单的LoginSDK, 并在多个App中进行植入,而且进行了帐号共享。依照以前的风格,将本篇博客所涉及的全部内容都会在Github上进行分享,下方就是github分享地址。欢迎交流,上述内容有什么不足之处,欢迎批评指正,谢谢。
github分享地址:github.com/lizelu/Logi…
你认为如何?请经过加咱们的交流群 点击此处进交流群 ,来一块儿交流或者发布您的问题,意见或反馈。
做者:青玉伏案 出处:www.cnblogs.com/ludashi/