因公司業(yè)務(wù)要求,需要開(kāi)發(fā)一款廣告SDK,自己之前未涉及到SDK開(kāi)發(fā),所以一路踩坑記錄如下:
【 前言 】
1、清晰解決的問(wèn)題和要求
一般而言,一個(gè)SDK必然有其深刻的業(yè)務(wù)背景;對(duì)SDK要解決的問(wèn)題和SDK的特殊要求,了解地越詳細(xì)越好;
常見(jiàn)的要求有:
- 禁止采集用戶敏感信息【安全方面】
- 核心代碼必須混淆【安全方面】
- 不可以有調(diào)試日志,不可以監(jiān)控上報(bào)【安全方面】
- 持久化的敏感數(shù)據(jù)要加密;【安全方面】
- SDK大小不可以超過(guò)XXKB:【其他】
…..2.選擇合適的開(kāi)發(fā)語(yǔ)言
大多數(shù)情況下,選擇Objective-C開(kāi)發(fā)就ok了,不僅能接入Swift開(kāi)發(fā)的項(xiàng)目,還能接入Objective-C開(kāi)發(fā)的項(xiàng)目;
當(dāng)然并非絕對(duì),具體根據(jù)業(yè)務(wù)情況決定;
【 SDK開(kāi)發(fā)注意事項(xiàng)】
1.確定SDK庫(kù)的類型
A、靜態(tài)庫(kù),鏈接時(shí)完整地拷貝至可執(zhí)行文件中,被多次使用就有多份冗余拷貝。
(我司選型采用靜態(tài)庫(kù))B、動(dòng)態(tài)庫(kù),鏈接時(shí)不拷貝,程序運(yùn)行時(shí)由系統(tǒng)動(dòng)態(tài)加載到內(nèi)存,供程序調(diào)用,系統(tǒng)只加載一次,多個(gè)程序共用,節(jié)省內(nèi)存。
(據(jù)說(shuō)早在WWDC2014蘋果在iOS上便開(kāi)放了動(dòng)態(tài)庫(kù),具體可以谷歌了解)這里簡(jiǎn)單說(shuō)一下Mach-O類型,為什么說(shuō)簡(jiǎn)單說(shuō)一下。因?yàn)樯钊胛乙膊涣私饬?,深入可以谷歌或度娘資料。
- Executable:應(yīng)用的主要二進(jìn)制
- Dylib Library:動(dòng)態(tài)鏈接庫(kù)(又稱DSO或DLL)
- Static Library:靜態(tài)鏈接庫(kù)
- Bundle:不能被鏈接的Dylib,只能在運(yùn)行時(shí)使用dlopen( )加載,可當(dāng)做macOS的插件
- Relocatable Object File:可重定向文件類型
2.Method Swizzling
簡(jiǎn)介:
Method Swizzling是Objective-C中運(yùn)行時(shí)特性之一,本質(zhì)是在運(yùn)行時(shí)交換方法實(shí)現(xiàn)(IMP);SDK有時(shí)候需要Method Swizzling利用hook一些系統(tǒng)(Objective-C)方法; 需要Method Swizzling的話,推薦使用 RSSwizzle,它是線程安全的Method Swizzling方案,優(yōu)勢(shì)是:不需要在+load()中實(shí)現(xiàn)方法交換 而且是 線程安全的;3.category的處理
category是項(xiàng)目開(kāi)發(fā)中經(jīng)常用到的,把category打包成靜態(tài)庫(kù)是沒(méi)有問(wèn)題的,但是在使用這個(gè)靜態(tài)庫(kù)時(shí),調(diào)用category中的方法時(shí)會(huì)發(fā)生找不到該方法的運(yùn)行時(shí)錯(cuò)誤(selector not recognized).
- 解決的辦法是在使用靜態(tài)庫(kù)的工程中配置other linker flags的值為 -ObjC -all_load,建議SDK中少用類別,因?yàn)橛袝r(shí)候會(huì)對(duì)項(xiàng)目造成影響;
4.對(duì)圖片資源和UI界面xib或nib文件的處理
.a和.framework兩種靜態(tài)庫(kù),通常都是把需要用的到圖片或者xib文件存放在一個(gè)bundle文件中,而該bundle文件的名字和.a或.framework的名字相同。
.a文件中無(wú)法存放圖片或xib文件,但是.framework中,也許需要單獨(dú)創(chuàng)建bundle文件的,因?yàn)閕OS系統(tǒng)不會(huì)去掃描.framework下的圖片等資源文件,也不會(huì)在項(xiàng)目中顯示,也就是說(shuō)即使放在 .framework目錄下,系統(tǒng)根本就不會(huì)去掃描,因此也無(wú)法發(fā)現(xiàn)使用.
(我司選用的是framework的靜態(tài)庫(kù))5.plist文件
如果SDK中沒(méi)有用到info.plist文件可以刪除,避免在工程中發(fā)生沖突,如果有用的記得在info.plist文件的名字加前綴,修改下plist文件的名字;
6.不要將第三方庫(kù)打包進(jìn) SDK
盡量不要將第三方庫(kù)打包進(jìn) SDK,如果要打包,最好也要將該第三方庫(kù)重命名,以避免沖突,pod引入的方式也會(huì)涉及到和APP宿主工程版本號(hào)不兼容問(wèn)題;
7.所有類名都應(yīng)該加前綴
SDK是給別人用的,如果類名不加前綴很容易重名。重名可能導(dǎo)致有沖突的風(fēng)險(xiǎn)。
8.文檔完整并且正確
需要有完成的開(kāi)發(fā)接入文檔以及Demo示例工程工開(kāi)發(fā)人員接入?yún)⒖?,每次升?jí)還需要完善對(duì)應(yīng)的升級(jí)日志;
9.SDK需要常規(guī)架構(gòu)支持
比如:i386 x86_64 armv7 arm64
- 模擬器32位處理器測(cè)試需要i386架構(gòu)
- 模擬器64位處理器測(cè)試需要x86_64架構(gòu)
- 真機(jī)32位處理器需要armv7,或者armv7s架構(gòu)
- 真機(jī)64位處理器需要arm64架構(gòu)
i386是針對(duì)intel通用微處理器32位處理器
x86_64是針對(duì)x86架構(gòu)的64位處理器
armv7|armv7s|arm64都是ARM處理器的指令集
i386|x86_64 是Mac處理器的指令集10.SDK打包framework腳本
正常打包framework需要通過(guò)終端的兩個(gè)命令行來(lái)完成
lipo -create "真機(jī)包路徑" "模擬器包路徑" -output "合并包路徑"
添加腳本后可以通過(guò)sh腳本實(shí)現(xiàn) 真機(jī)模擬器腳本合并framework 打包。.......
【 結(jié)尾 】
最后,溝通Plus
- SDK會(huì)被多個(gè)宿主App接入,不同的App環(huán)境不同,SDK可能遇到很多問(wèn)題,積極幫助解決后,記錄下來(lái),作為后續(xù)其它宿主App使用SDK的重要參考;
- 及時(shí)同步SDK最新信息;SDK的bugfix版本,要及時(shí)同步,并幫助業(yè)務(wù)升級(jí),盡量減少損失;
- SDK重大升級(jí),需要業(yè)務(wù)方至少有一個(gè)人對(duì)SDK有比較全面的了解;