公司由于业务需求,为减少下游供应商的开发成本,缩短开发周期,特此开发SDK,然后编写SDK使用文档,直接让下游供应商接入即可。SDK只暴露头文件给接入者,他们并不能看到.m文件里是如何实现的,这样就可以快速的把公司的需求和产品直接快速的传达到下游供应商,利于公司的推广和下游供应商的使用。
什么是SDK:
软件开发工具包(缩写:SDK,英语全称:Software Development Kit),一般都是一些软件工程师为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件时的开发工具的集合。
在OC的开发中,我们涉及到的一般是静态库(.a)或者动态库(.framework)。(注:不是所有的.framework就一定是动态库)
静态库与动态库的区别?
静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。表现形式为 .a和.framework。动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。 表现形式为 .dylib和.framework。注意:动态库只能苹果使用,如果项目中使用了动态库不允许上架(如:jspatch)
a与.framework有什么区别?
.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。 .a文件不能直接使用,至少要有.h文件配合(微信的SDK就是这种形式),.framework文件可以直接使用。 .a + .h + sourceFile = .framework。 建议用.framework。再者 静态方式开发,一直是iOS SDK开发的主流方式
静态库与动态库的区别?和 a与.framework有什么区别?参考的是:iOS SDK开发(入门指南) - 掘金,然后本人稍加了改动。
创建静态库工程
本人是用Xcode 10.2.1 创建,是以.framework形式开发静态库的。
选择创建.framework静态库项目,语言选择Objective-C。虽然现在swift已经到5.0了,但是大家作为开发者,都是从OC开始的,所以用OC,受众面广,大家都会,用起来方便。
以上俩个图片步骤就是创建静态库。
静态库配置
TARGETS-General-Deployment Info,设置支持iOS系统的最低版本和支持的设备
TARGETS-Build Settings-Linking ,选择 Static Library(静态库),系统默认的是Dynamic Library(动态库)。这个一定要记得改,切记一定要改,否则你创建的就不是静态库
TARGETS-Build Settings-Build Options,将 Enable Bitcode修改为No.
Edit Scheme - Run - Info - Build Configuration 修改为Release
在SDK项目中创建Bundle
个人以为有以下俩中方法:
1:在桌面上创建一个空的文件夹,然后文件名称修改为.bundle结尾,那么系统就把这个文件转变成bundle文件,然后拖入你的SDK项目中。(本人亲自测试,可以的)
2:选中Xcode项目,然后选择左上角的 File-New-Target-macOS-Bundle
然后做如下配置:
TARGETS-TestBundle(你的bundle名称)-Build Settings -Architectures-Base SDK 设置为iOS
这里在SDK工程中创建bundle后,在General-Signing可能会报错,例如:
解决方法是:把 Automatically manage signing 前面的✔️去掉,然后在重新打上✔️,弹框选择Enable Automatic ,然后在 team 一栏在选择一个开发者账号即可。
TARGETS-TestBundle-General-Deployment Info:修改 所支持的iOS版本和设备
TARGETS-TestBundle-Build Settings-Build Options:修改 Enable Bitcode为NO
TARGETS-TestBundle-Build Settings-Deployment-Installation Directory清空其里面的内容
TARGETS-TestBundle-Build Settings-User-Defined-COMBINE_HIDPI-IMAGES改为NO,双击,然后修改为NO .
把MyTestSDK改成TestBundle,然后 Edit Scheme-Run-Info-Build Configuration 修改为 Release
到此为止,bundle目配置已经完成。
创建好bundle,配置好后,bundle的样式为如下所示:项目中多了个TestBundle文件夹,Procucts文件夹下多了一个TestBundle.bundle文件。
这个时候你选择MyTestSDK.framework,右键Show in Finder是显示出来的只有MyTestSDK.framework,而没有TestBundle文件。这时候把SDK项目MyTestSDK改成TestBundle
然后你选择模拟器或者是真机,编译一下,SDK项目下的Products下的TestBundle文件颜色由红色变成白色。然后选中TestBundle,右键Show in Finder你会看到TestBundle。
其实把项目封装成一个SDK,就是创建一个静态工程,然后把你的项目文件和资源文件放入静态工程,然后打包编译。
把项目放入SDK工程中
把你的自己写的项目,暴露好头文件,自己测试好没有任何bug了,然后把功能实现的.h 和.m文件以文件夹的形式拖入到SDK项目中。项目中所用的图片,全部放到TestBundle里面。选中MyTestSDK.framework,右键Show in Finder,选中TestBundle.bundle,右键 显示包内容,把项目中的图片资源放进去
1:放进bundle里面的图片,不能用
加载,因为这样的加载方式,图片必须放入到Assets.xcassets文件夹中。但是SDK项目中,不存在这样的文件夹。所以如果项目中有图片,必须用下面的方式加载:
如果你的项目中用的有XIB,放入SDK后,打包编译时系统就会放入bundle中。
2:把代码放入SDK工程中,直接拖入即可,然后 TARGETS-MyTestSDK-Build Phases-Headers,设置公开头文件。
你拖入SDK项目中文件的头文件(.h),系统会默认发放你在Project下,你选中,移动到Public下面即可。
上图中设置的每一个公开头文件,都得在你创建的SDK项目下的.h文件中,需要引入头文件。
3:编译bundle
在MyTestSDK工程中,TARGETS-TestBundle-Build Phases,在其copy Bundle Resources中,点击+号,添加资源
编译bundle
这样你选择的xib或者其他资源就添加到bundle里面了。
SDK编译
SDK编译时会根据你选择的是真机还是模拟器,生成不同的SDK,你选择了真机,那么编译时就会生成真机的SDK,无法在模拟器上运行;你选择了模拟器,那么编译时就会生成模拟器的SDK,无法在真机上运行。我们为了使用,是要把真机和模拟器SDK合成一个,具体的合成步骤,稍后会介绍的。
SDK添加都新的项目中
command + B 编译一下,然后再SDK工程中的Products文件下,选中framework,右键 Show in Finder,复制后,导入你的新工程中。当你把SDK导入新工程中时,framework会自动添加到Build Phases-Link Binary With Libraries 中。如果framework没有加入到Link Binary With Libraries里面,则需要你自己点击 + 号,自己人为导入。
新工程配置如下:要和SDK的配置保持一致。
在新的工程中添加如下的代码既可运行
SDK真机和模拟器合成。
上面说过,.framework静态库编译时会生成真机的framework和模拟器的framework,开发过程中为了别人使用方便,我们需要把真机的framework和模拟器的framework合并成一个framework,使之在真机环境和模拟器环境都可以运行。我是通过手动的方法合成的,没有采用脚本的方法,后期会逐渐加入脚本的方法合成模拟器。
1:真机framework,静态库工程,
静态工程选择一个真机(或者 Generic iOS Device),command + B 编译运行,选择Products-MyTestSDK.framework,右键 Show in Finder,
Release-iphoneos文件夹下的framework就是真机的framework.
打开终端,输入 lipo -info 真机framework文件路径(把framework拖进去) ,回车,可以查看framework所支持的框架类型
framework拖入终端后,路径最后一定要加上 项目的名称(/项目名称)。当你看到 armv7、arm64 时表明你这真机的;
2:模拟器framework
静态工程选择一个模拟器,command + B 编译运行,选择Products-MyTestSDK.framework,右键 Show in Finder,
Release-iphonesimulator模拟器文件夹下的framework就是模拟器的framework
打开终端,输入 lipo -info 模拟器的framework文件路径(把framework拖进去)
framework拖入终端后,路径最后一定要加上 项目的名称(/项目名称),回车,你会看到最后的 i386 x86_64,说明是模拟器的
3:真机framework和模拟器framework合成
使用 lipo -create 进行操作
lipo -create 真机路径 模拟器路径 -output 真机路径
切记每个路径结尾都要加上你SDK工程的名称(/文件名称),有些文章上没有说明要加你SDK所在的文件名称,则会每次合并都不成功。
敲击回车后,终端命令行什么也不输出,则证明合并成功了,导入项目中,真机和模拟环境下都可以自如运行了。
用lipo -info 查看一下,就会看到 armv7 i386 x86_64 arm64
如果路径后面你不加SDK所在的工程名称,就会把下面所示的错误:
使用此方法把真机和模拟器的framework合成一个,有一个缺点:一旦你的静态工程中更改了代码,你就要在重头来一遍,重新合并生成。这个方法比较笨,但是很好掌握。还有一种合并真机和模拟器的方式就是通过脚本,这种方法后面在介绍。
以后就是静态SDK创建及其演示的全过程。
项目导入SDK运行后可能产生的bug
1:找不到某个文件
解决方法:请按照下面方法改为YES
后记:
SDK开发,没有开发过的小伙伴可能感觉很陌生,无从下手。再者一次就开发成功估计可能行不大,大多数开发者都是第一次开发SDK,毕竟很少有公司会专门开发SDK给别人用,大公司除外。所以建议大家先按照步骤,做一个简单的SDK,练练手,知道问题出在哪里。有会即使你严格按照文章上的步骤一步一步来,也不可能马上搞定,会有意外的问题。在我的简书上有片文章iOS开发:SDK开发相关文档 - 简书,上面搜集了我开发SDK时所参考的文章,在加上我这边文章,开发一个SDK应该没问题了。下个文章,我会介绍一下SDK开发的一些规范。
如果有不妥之处,欢迎大家下方留言。本片文章是笔者开发过程中的个人总结,不喜勿喷。