最近业务需求需要开发一个SDK集成到友方App中,于是就有了本文中的这些经验(掉坑-爬坑-掉下一个坑)。
成都创新互联是专业的尖扎网站建设公司,尖扎接单;提供网站设计制作、成都网站制作,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行尖扎网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!
这个其实不涉及技术问题,但是也需要谨慎,因为我们的SDK属于一个比较完整的业务模块,所以依赖的第三方库还是挺多的,其中就用到了高德地图,(开始我们就用的通用版本,结果友方用的是另一个版本,结果为了能够集成成功,后期不得不更改高德地图版本),所以建议如果是这种明确合作方的SDK这种框架还是需要提前沟通好。
PS:忍不住吐槽一下,高德地图整出一大堆乱七八糟的框架目的是个啥呢,又不能互相兼容,开发者还不知道选择哪个合适。
原生App开发,资源文件最多的无非是图片,在平时项目开发中一般会放到asset文件夹中,但是在SDK中,需要创建.bundle文件(建议与项目同名)对资源文件进行管理。
该方法在项目中使用举例:
简单来说,在生成模拟器.framework中与生成真机.framework时,都存在arm64架构,网上提供的通过后期命令行删除某个arm64的方式始终无法解决该问题。此时需要配置如图选项,大概意思是在模拟器生成的.framework的框架不再添加arm64,后期将模拟器库与真机库合并,各个架构模式就都存在了。
模拟器包与真机包合并命令行
制作远程私有库的教程有很多,此处就不展开来仔细说明了。 iOS开发: 配置CocoaPods远程私有仓库 重点说一下针对非开源的.framework框架,如何去配置spec
设置自己的非开源SDK
设置项目SDK相关的资源文件夹(bundle)
当自己开发的SDK中包含类目文件时,编译就会有提示找不到,此时需要在设置页other_laflags添加'-objc',但是在SDK中无法设置,只能写在spec文件。
当调用pod lib lint --verbose --use-libraries时报了如下错误:
Ld .../Build/Intermediates.noindex/App.build/Release-iphonesimulator/App.build/Objects-normal/arm64/Binary/App normal arm64
解决方案:
经历了整个SDK的完整开发流程,一步步排除问题,最终达到了最终结果。在此感谢一起解决问题的同事--卞老板。
尽管App store里存在众多种类繁杂,服务各异的应用,但所有App都有一个共同的目标:提供 极致的用户体验。
好的用户体验是由许多因素构成的。我们需要知道,一款好产品背后必定是经过团队多方面打磨、迭代而成。产品迭代必不可少的一项内容,就是取决于你所使用的工具,比如iOS SDK(软件开发工具)开放的通用模块,从beta测试和错误监控到用户行为分析和A/B测试,都有相应的产品,可以大大缩减金钱、时间成本,从而提高应用整体运营的敏捷性。
这里列出了几款iOS必备软件开发工具,直接根据需要配置即可。
地址:
UserTesting的按需测试平台由一个超过一百万测试者的座谈小组组成,可以在移动设备上测试网站、App甚至是原型。在这里几小时内就可以得到人工的反馈意见,包括一段记录测试过程的视频和一份完整的文字报告。开发者可以通过这些内容详细地了解用户的使用习惯,以及产品在使用过程中遇到的各种问题。
主要特点:
超过百万的用户网络
可直接面试
视频模式和自动转录信息
地址:
openinstall SDK能提供多种服务,包括最让开发者头疼的iOS多渠道统计,相对iTunes Connect 的“营销活动”统计维度更丰富,且实时灵活,适合多渠道推广使用。同时提供免填邀请码安装、一键拉起(Deeplink)、携带参数安装、地推统计、CP结算、广告投放统计等多个使用场景以及应用优化功能,让App用户体验更佳,拉新转化率更高。
主要特点:
多渠道携带参数统计
免填邀请码等优化用户体验
提高拉新转化率
地址:
另一个具有多种功能的SDK是Instabug ,它包括了bug报告工具,让您的用户可以将bug发送给您;还有崩溃报告工具,可以向您发送所需的堆栈跟踪信息,甚至不用导航。您还可以对比当前版本和前一个版本,观看用户操作的屏幕记录。Instabug 可以与您的工作流程集成,然后通过Slack和JIRA发送提醒给整个团队。
主要特点:
bug屏幕记录
交互式用户反馈
Bug的建议和类型分析
地址:
Optimizely 的试验平台给web网站、移动端网页和移动端App提供解决方案。移动工具可以让您很流畅地对应用的各个部分进行即时实验。快速迭代是这个工具的特点,您不需要等待应用商店的审核即可更新应用。同时,Optimizely 还可以让您根据精准化的目标市场创造个性化的体验。
主要特点:
即时推出和分阶段推出
视觉编辑
自定义受众以及精准化目标定位
地址:
Foresee 提供了一套多渠道的“用户体验”工具,其中包括自助用户反馈工具。通过Foresee的反馈工具,您可以鼓励用户填写简单的调查问卷,让他们提出问题,以避免问题扩大化。此外,您还可以为核心用户快速部署评级和审核提示。此外,Foresee还可以重播整个会话,提供App用户体验的全貌。
主要特点:
简单,自助化
个性化评分和评审
提醒会话重播
相比于采购需要大量定制化开发或自研的产品,使用标准化通用的SDK,可以大大缩减金钱、时间成本,从而提高公司整体运营的敏捷性。
这就像你需要用电,但并不需要从头建发电厂,更明智地做法是主动关注哪些能力是市面上的SDK厂商已可提供的,哪些还不成熟;做好SaaS、定制化软件和自研工具之间的分配,为那些需要“拼速度”的一线业务准备好“利器”。
最近公司由于业务需求,需要提供一个SDK以供第三方公司的集成开发,之前没有这方面的开发经验有点迷茫。然后就在网上查看了一些相关的资料,自己研究了一天,成功的封装出了自己iOS开发过程中的第一个SDK包。同时也是为了以后开发SDK留下一个比较完整的笔记。
SDK的英文全名是:software development kit,翻译成中文的意思就是“软件开发工具包”,我个人的理解就是一个工具包,完全可以理解成开发中我们的一个公共类。
二、怎么实现SDK的封装呢?
1.打开Xcode开发工具创建我们的工具类
注:本文中使用的开发工具为xcode9.3
创建完成后
创建完成后,我们新建两个继承于基类的文件,一个用于封装网络请求一个用于封装我们需要提供给他人使用的方法以及需要动态改变的参数。
2.网络请求添加到SDK中一起封装
因为我们封装的SDK有的数据涉及到网络请求,所以我们封装的时候,顺便把需要用到的网络请求也封装进去。
1).使用cocoapods导入第三方库AFNetWorking
具体使用 见印象笔记内容,包含了使用cocoapods遇到的问题以及解决方法:
2).在封装的SDK中如果涉及到使用第三方的库引用的时候,一定要在.m文件中进行引用
3.做完想要封装的文件后,开始进行封装
先进行编辑设置,在product --Scheme---Edit Scheme
此处必须是release,不能用debug模式,选择SDK是在iOS 、tvOS还是watchOS 4上面运行的SDK,在这儿我们选择iOS
在build Setting里面 搜索linking 设置Mach-O Type 为 static library
在build Phases --- headers 中添加需要暴露的类,将Project里面想暴露的文件.h拖动到Public里面进行文件暴露
完成所有设置后,我们进行真机编辑和模拟器编辑最后合并成一个可以在真机和模拟器上运行的第三方SDK,
4.到这一步我们的SDK封装就差最后一步了,合并成能在真机和模拟器上运行的SDK
选中编辑好的包,我这儿是Demo_SDK.framework然后右击显示文件内容
找到这两个文件后,我们开始合并,得到我们想要的SDK
1).打开终端---输入lipo -create 加上文件路径
1.为真机的文件,2为模拟器的文件,3为合并后输出问的地址
注意:我们所合并的文件是Demo_SDK,并不是所有的文件
合并到处文件为lipo结尾的
更改合并和的文件名称和合并前文件名称相同,并且去掉后缀。用合并和的文件替换掉和并前的文件
合并完成后拷贝处我们封装的SDK,在其他项目中引用就可以了
总结:截图比较多,为了照顾像我这样的小白,希望大家理解。第一次写,不喜勿喷,这只是作为自己的个人笔记,如果有什么不对的地方,希望大家指出一起交流学习,Thanks♪(・ω・)ノ
Demo链接:
iOS SDK开发就是为某一个应用场景、或领域、或需求,提供一个已实现的、封装好的、可供直接使用的模块。
其主要由两部分组成:用来为类型或常量声明的头文件列表、具体实现的二进制文件。
所以SDK开发中的主要问题点集中在:
1. 头文件是否能被使用的工程索引到
2. 二进制文件是否能被使用的工程搜索到
本篇文章不写制作SDK的具体步骤,仅仅讨论制作SDK时的一些情形。
SDK开发中关于头文件设置:
凡是提供给外界使用的类、结构体、枚举、常量等,定义它们的头文件必须要在工程的Build Phases-Headers-public下面。并且这些头文件都需要包含在与SDK工程同名的头文件中(这条不是必须,只是这么做会显得更加规范。别人使用SDK的时候,只需要引入SDK同名的头文件即可)
设置库文件生成动态的还是静态的:
Project Name-Target Name-Build Settings-搜索框搜“Mach”-修改“Mach-O Type”为动态或静态,则相应可生成动态或静态的库文件。
先解释说明以下图片中出现的工程名字:
SDKDemo :制作的向外提供的SDK库文件(与SDK工程名同名)
SDKApp :引用SDK库文件(本文指的是SDKDemo)的App工程
SDKStatic :新建工程时,选择iOS-Framework Library-Cocoa Touch Static Library. 用来生成.a文件的工程
SDKFramework : 是个Framework库文件(可能是动态的,也可能是静态的),用于模拟被SDK依赖的.framework文件
下面分几种情况来讨论SDK开发的注意事项:
1. 生成动态SDK库文件。
创建工程的时候,根据默认配置编译是生成动态库的。
App工程中引入动态库的时候,需要在
App工程:Project Name-Target Name-General-Embedded Binaries下添加引入的动态库。否则运行时会报如下类型错误:
嵌入动态库编译后,生成的App文件中会多一个Frameworks目录(可右键.App文件查看包内容),里面全是Embedded Binaries下添加的动态库
2. 打包为静态库
SDK工程:Project Name-Target Name-Build Settings-搜索框搜“Mach”-修改“Mach-O Type”为静态库
App工程引入静态库很简单,直接引入就行,不需要额外配置:
tips:
合并真机与模拟器版本时的命令格式为:
lipo -create 模拟器版本的路径 真机版本的路径 -output 合并后的版本存放路径
1. 合并时lipo -create接收的模拟器版本和真机版本两个参数的前后顺序没有关系,合并后的版本通过命令查看架构信息显示结果是完全一致的。模拟器架构信息显示在前,真机架构信息在后。
2. 合并后的版本无论替换真机版本的Framework中的目标文件还是模拟器版本的Framework中的目标文件,App工程中引入被替换的Framework后在真机和模拟器上都能跑起来
首先创建SDKStatic工程,生成一个.a文件。
该工程只是简单继承了UIButton,并重写了initWithFrame方法。为每一个MyButton对象默认生成标题和背景色:
生成的.a文件如下,可以看到里面包含了MyButton.o文件:
在SDK工程中引入.a文件。下面分两种情况来看生成的SDK库文件:
1. SDK库文件做成动态库(设置方法看开头部分)
.a文件内容被整合进了SDK动态库文件中,引入App工程中时,只需要引入SDK动态库就可以了
2. SDK库文件做成静态库(设置方法看开头部分)
包中的信息:
.a文件内容同样被整合进了SDK静态库文件中,这个更好理解。引入App工程中时,只需要引入SDK静态库就可以了
总结下:
制作SDK库时,如果有依赖的.a文件,则最终生成的SDK库文件会合并.a文件的内容,而不论SDK库文件是动态还是静态的。
下面的SDKFramework是个Framework库文件(可能是动态的,也可能是静态的)
SDKFramework工程添加的内容和SDKStatic工程是一样的。也是自定义MyButton,默认生成标题和背景色(拷贝文件到工程):
SDKDemo工程自定义了MyView,默认生成的MyView对象添加了一个MyButton按钮和背景色:
1. 如果.framework文件是动态库
a. SDK打包为静态库,如下:
静态SDK包和动态SDKFramework.framework文件是彼此独立的。引入静态SDK包时,必须也导入SDKFramework.framework,否则编译不过,因为静态包有引入动态库中的符号。
b. SDK打包为动态库,如下:
两者还是彼此独立的。动态SDK包中会记录依赖的动态.framework rpath,App运行时,dyld会根据这个信息去加载对应的.framework依赖文件。如果找不到App将会在启动时奔溃...
2. 如果.framework文件是静态库
a. 首先SDK打包为动态库看看:
经实践,依赖的静态库会被整合进动态SDK包自身中。App中引入时,只需要导入SDK包就可以。我们在SDKApp中导入SDKDemo,运行可以看到如下效果:
b. 再看看SDK打包为静态库:
根据上面截图中信息,App中导入SDK包时,也必须导入依赖的.framework了。否则编译时将会出现如下图所示找不到符号的错误:
追加导入依赖的.framework,再次编译运行。OK!!!
总结:
1. 依赖的.framework为动态库
制作的SDK库文件不论动态还是静态的。和依赖的.framework文件本身是彼此独立的,不会发生符号整合的现象
2. 依赖的.framework为静态库
如果制作的SDK库文件是动态的,则依赖的.framework静态库内容会被整合进SDK库文件中
如果制作的SDK库文件是静态的,则彼此是独立的
这里又得分几种情况讨论:
1. Podfile中不使用use_frameworks! pods库生成的是.a文件
a. 如果SDK制作成静态库:
SDK静态库不会整合Pods里三方库中的符号,最终导入App工程时,需要SDK静态库、Pods中的三方库文件一起导入
b. 如果SDK制作成动态库:
Pods库中的符号会被合并整合进入SDK库中,导入工程时,只需要导入SDK包就OK了
2. Podfile中使用use_frameworks! pods库生成的是.framework文件。其中Pods_工程名.framework文件是个静态库,管理的第三方库生成的是framework动态库
a.如果SDK制作成动态库:
SDK中会包含引入三方库的rpath,App中引入SDK包时,也必须引入三方库,否则dyld加载不了指定库导致App启动时奔溃
b. 如果SDK制作成静态库:
静态SDK中会忽略Pods中的库中定义的符号(也即彼此是独立的)。如果静态SDK中引用了动态pods库中定义的符号,只要在App工程中也导入pods中动态库,并在embeded binaries中添加。一样是可以编译运行的。
其实怎么编译,SDK工程中是个什么情形都不重要。重要的是要明白库文件的本质,及它是如何发挥作用的?在什么阶段发挥作用?然后学会查看编译运行时的报错信息,并配合使用otool、nm、lipo、ar、file等这些命令去查看库文件的一些信息,最终追踪定位到问题。
原谅我最后都没怎么贴图了,因为流程都和前面差不多。我也写的手累了。如果你还有什么疑惑可以在下面评论,我会尽量及时回复。
公司开发的SDK,是集成了各个平台的商品,包括购买、分享、提现等功能,为了加快进度,我是使用了一些第三方。但是有些需求,比如分享到微信朋友圈或者还有,必须用到微信的SDK。考虑到后期的维护成本和集成,笔者采用了cocoapods管理第三方库。
笔者有片文章专门介绍SDK的开发步骤的,大家可以参考,我这里就直接进入主题了。
首先,你创建一个静态的framework工程MyTestSDK,把这个工程集成cocpapods,至于如何集成cocpapods,网上有教程,自己搜索。这个时候把你项目中所用的第三方库添加到Podfile文件中,然后 pod install。这个时候你command + B 编译运行,如果你的第三方库中还有Bundle资源,那么编译后,第三方库的bundle资源会被编译,一起放到Products文件下的framework文件中,右键Show in Finder就会看到。如下图所示的MBProgressHUD文件夹,里面都是MBProgressHUD第三方的资源文件。
然后把你的项目放入SDK工程中,编译运行一下,看看有没有错误。之所以先把SDK工程选用cocoapods管理,就是怕你的项目放入SDK中运行报错。没有任何问题,直接编译即可。
由于SDK中的第三方是通过cocoapods管理的,所以接入者的项目也要用cocoapods管理。
1:把SDK工程中,Products文件夹下的framework文件copy到项目中,最好项目中建立一个文件夹,专门放SDK和bundle。我是放到了一个文件夹中,方便分类寻找。如下图所示:
2:打开终端,cd到SDK所在的文件夹下,执行如下命令,回车,创建spec文件。
其中,MyTestSDK是你的SDK名称。
创建出来的spec文件,是个很长的文件,但是大部分都是注释的,我这里只提取了有用的信息展示出来:
然后把spec中依赖的第三方库,逐个加入到项目中的Podfie文件中。然后 终端打开,cd到自己的项目中,pod install即可。
本人亲自测试过的,No Problem。当初感觉SDK如果依赖了第三方库,接入的项目中也有同样的第三方库,会不会冲突啊,感觉好难搞啊。事实证明,通过spec进行依赖,可以很好的解决这个问题,也就没有那么麻烦了。
首次开发SDK还是遇到了很多问题,运行出现很多bug,但是最后还是一一解决了,就是没有记录下bug和解决发的方法。
1;path路径不对,就会报错 ,如下
是因为我把路径写成了:
其实正确的写法是:把“/”放在前面
2:SDK中有第三方,但是项目中的Podfile里面没有这个第三方,报错如下所示:
解决办法是就是在项目中的 Podfile里面加入缺失的第三方库,重新 pod install。
IOS开发有些时候通过制作SDK进行组件化, 封装化开发很方便, 那么怎么制作一个可用的SDK呢? 直接上干货
当前环境:
MacOS 12.3.1
Xcode13.4.1
Intel Core i9
xcode → File → New → Project
Frame Library → Framework → Next
Product Name 中填写SDK名字 → Next 之后选个自己能找的到的地方保存工程
创建好了最终是这个样子
先修改 Deployment info 部署信息, 这个要根据自己的 目标工程 配置。例如 我加入的目标工程支持到 ios10.0, 不支持iPad, Mac, 那么我创建的SDK也要对应修改
其实自己随便一个项目加进去即可, 留意下版本号对应即可
接下来 Command + N 创建一个类便于后面调用
例如我这边创建一个 SpriteFactory 类, 类型是 NSObject , 并写入一个实例方法 factoryProductSprite
建好之后, 在公共文件 ProductSprite.h (第一个, 你自己建的那个名字), 引入头文件. 留意下引入文件格式即可
接下来我们需要修改一下 Build Settings 中部分内容
接下来我们建立个组群, 管理下SDK
建完之后如下, 多了一个这个
添加 framework 的脚本文件, Build Phases 点击 + 选择 New Run Script Phase
把这个复制进去
上方选择新加的 Targets 选择 Any iOS Device 运行
由于我们刚才已经写脚本了, 所以会自动生成模拟器真机的SDK, 并且自动弹开, 如下
其他项目如果想使用, 把 .framework 拖进去或者复制项目再 add 进去即可
加入之后如下, 留意下 General 中 Frameworks, Libraries, and Embedded Content 这快, 如果没有(老版本), 需要手动加进去 .framework
在合适地方调用, 引用头文件格式 #import "ProductSprite/ProductSprite.h" , 下面写进去对应方法
运行可看到
动态库如果正常按上面方式处理会报错, 例如
Targets → Build Settings → Mach-O Type 为 Dynamic Library
运行时候会这样Crash
目标文件: Build Phases 点击 + , 选择 New Copy File Phase
点击 + , 选择对应动态库加进去, Destination 留意选择 Frameworks
修改 Targets → Build Settings → Build Options → Validate Workspace 为 Yes
配置完之后再运行, 正常打印