iOS SDK開發

內容概述

SDK定義上是指軟件開發包,對應iOS端來說就包含了庫文件、頭文件、資源文件等文件的集合。SDK開發就是在保證sdk源代碼安全的情況,給開發者一個可方便快速接入的,兼容多個iOS系統、便于真機模擬器調試、可以上線AppStore的庫。這句話包含的幾個重要的信息將在本文中逐步詳解。

本文將從iOS系統中SDK開發過程中需要考慮和注意這兩方面入手,講述SDK的設計:

1. 工程設置

2. 接口設計

3. SDK需要考慮的方面

4. checklist


工程設置

創建一個SDK工程通常通過下面方式:

目前SDK主流開發方式是第一種,即工程的產物提供framework,因為可以將庫和頭文件、資源都放在其中,當然可以選擇第二種,工程的產物是靜態庫,如果分發需要將頭文件與庫一并提供。

對于framework來說,需要注意xcode6以后framework在Xcode默認配置的是動態庫:

“Frameworks for iOS. iOS developers can now create dynamic frameworks. Frameworks are a collection of code and resources to encapsulate functionality that is valuable across multiple projects. Frameworks work perfectly with extensions, sharing logic that can be used by both the main application, and the bundled extensions.”

大意是xcode6(iOS8)后開發者可以創建自己的動態framework,其中包含可以跨工程使用的代碼、資源。動態framework只能用于企業證書分發的ipa包中,對于上傳appstore的所有產品必須使用靜態framework,否則會被拒絕。但是系統提供的動態庫dylib和framework是可以使用的,? 更正為:iOS8開始,apple放開了動態庫的使用,用戶可以通過xcode創建動態庫的framework,并且集成到app中,提交到appstore已經不會被拒絕。動態庫和靜態庫的區別可參考之前的文章,? 下圖是靜態framework的使用:

所以注意工程需要配置一下:


對于動態framework的使用稍有區別,需要單獨將framework嵌入到ipa安裝包中,因為動態庫的特點就是運行時加載,所以app的可執行程序中并不會鏈接其使用的動態庫,需要將動態庫和可執行程序同時放在安裝包中:


此工程編譯打包出來的app文件中,如下圖所示,會增加一個Frameworks文件夾,里面存放的正式嵌入的動態庫:


接口設計

總體來說SDK接口設計和類的設計相似:

1. 首先需要根據SDK中模塊劃分根據“單一職責原則”、代碼的依賴性分為不同的類;

所謂單一職責其實就是高內聚,保證一個類、一個接口只完成一個職責,不貪大貪全。

2. 接口設計也要滿足“單一職責原則”;

例如即時通信的群組消息中一個群大概有群名稱、群成員、群主、群頭像、群主題等幾個信息要素,我們設計接口時不能因為簡便而用一個或兩個接口提供所有這些信息,而是應該根據常見業務將上面信息分為以下接口: 獲取群信息(群主、名稱、頭像), 獲取群成員、獲取群主題 這三個接口,或者根據情況將獲取群信息分解為三個獨立的接口。

這樣設計的好處就是業務調用方可以根據實際情況某些case只調用其中一個接口,等到其他case再調用其他接口,這樣可以保證每個接口的信息量沒那么大,保證請求的及時響應和信息的及時展示。

3. 接口命名可讀性強,拼寫正確;?

要避免以下幾種形式的接口命名:

`createGroup:(NSString *)title`

`GroupWithTitle:(NSString *)title`

`creatGroupWithTitle:(NSString *)title`

三種命名分別的問題是: 第一種命名沒有對參數進行描述, 第二種命名沒有對接口的動作進行描述,第三種命名create單詞拼寫錯誤。

所以一個正確的命名應該是保證拼寫正確的情況下,按照(省略主語)謂賓這樣的格式:

`createGroupWithTitle:(NSString *)title`

4. 接口參數校驗:考慮用戶使用情況,給予充分提示,減少問答

有些接口圖方便可能設置成這樣:

- (void)queryGroupMasterViaGroupId:(NSString *)groupId? requestSucess:(RequestGroupMasterSucess)success requestError:(void(^)(NSString *errorType)) error;

可以看出對于錯誤的反饋是通過參數error的block回調出來,block中的errorType對應錯誤信息,但這樣的接口設計可能無法滿足開發者的需求:只有錯誤描述字符串,實際開發者可能使用一個int型code用于判斷錯誤性能更高,代碼更清晰,即使直接將errorType字符串的錯誤以toast形式展示出來,這個字符串也有可能不是開發者實際想要的提示語。


所以最好的錯誤回調應該是至少包含錯誤碼,最好包含錯誤描述(中英文兩種),如下面例子:

-(void)requestGroupMasterViaGroupId:(NSString *)groupId? requestSucess:(RequestGroupMasterSucess)success requestError:(RequestGroupMasterError) error;

其中回調的枚舉定義如下:

typedef void (^RequestGroupMasterError) (CMIMError * error);//獲取群主詳情失敗回調

回調的參數是一個CMIMError實例:

@interface CMIMError : NSObject

@property (nonatomic, assign) CMIMErrorCode code;

@property (nonatomic, readwrite, copy) NSString *codeDescription;

@property (nonatomic, readwrite, copy) NSString *detailDescription;

+ (instancetype)errorWithCode:(CMIMErrorCode)aCode;

- (instancetype)initWithCode:(CMIMErrorCode)aCode;

從該實例的定義可知道,實例中包含錯誤碼和錯誤簡單描述、詳細描述。


需要考慮的方面:

SDK開發就是在保證sdk源代碼安全的情況,給開發者一個可方便快速接入的,兼容多個iOS系統、便于真機模擬器調試、可以上線AppStore的庫。這句話包含的幾個重要的信息將在本文中逐步詳解。

還記得開篇時說的這個定義? 這個定義對應了下面幾個需要注意的地方:

1. 必要調試信息

對于我們提供給別人的庫,默認應該是關閉log選項的,但是有些時候為了協助客戶或者開發者定位SDK中問題,可能需要log信息,這樣我們在設計時需要在代碼中配置log,可以參考大牛的框架,有整個log的各個級別的開關,控制log的總量和詳細程度。

2. category、第三方庫、類的命名、宏定義命名需要獨一無二

我們xcode編譯鏈接時經常會報出這樣的錯誤:盜個圖:

這類問題都是由于重復的定義導致,包括類名的同名、宏定義的同名、category的同名等,解決方法最簡單的就是將同名之一改成其他名字,如果無法修改則需要通過lipo指令來解決。

3. 頭文件、屬性暴露合理

保證代碼安全就是保證頭文件暴露合理,并且頭文件中只暴露開發者需要用到的屬性(定義好readonly屬性)和接口,這樣可以保證開發者不會錯誤調用其他接口或屬性使SDK內部狀態或邏輯錯亂。

4. 支持的最低系統

通過app可能根據用戶群體有不同的最低系統支持,例如目前很多app已經不再支持ios8以下系統,但是SDK作為app的內核,需要保證不同客戶的需求都能滿足,所以SDK應該盡可能保證支持最低系統,一般到iOS6.

5. 支持模擬器調試

為了便于開發者調試,需要支持模擬器調試,所以在打包framework時需要有x86和i386版本,并通過lipo指令將二者合并到armv7 v7s arm64中去。

6. crash跟蹤

為了及時定位客戶使用SDK導致的crash,SDK中也要處理crash信息,并及時上報給我們。不建議使用友盟或bugly等商用SDK來收集crash,因為開發者一般也會集成這類SDK,所以很容易沖突,最好是自己寫代碼實現,原理首先是收集到程序的exception或signal,這時將相應的堆棧信息打印輸出上傳到服務器或者我們的郵箱中。


發布前checklist

為了保證每次上線的準確無誤,必須制定一個完備的checklist,每次發布之前對照checklist來逐個檢查,才能保證各項準備達到。下面列出幾個基本的檢查項:

1. 系統架構是否覆蓋完全,

使用lipo指令查看支持的架構,模擬器是否支持? arm64必須支持,否則無法上架

2. 版本號及發布日志?

確定準確的版本號,并根據當前版本詳細描述此次發布的更新點,這樣方便開發者熟知改動的地方,便于評估對以前版本影響和使用新版本的成本,也便于我們定位問題。

3. log系統

關閉log輸出,并屏蔽一些開發的調試代碼或者提示框。對于一些尚不穩定的初始幾個版本,由于問題比較多,開發者可以暫時打開log開關,這樣在出現問題的時候便于定位,等一些版本后相對穩定之后,關閉log。

注意:日志需要制定相應的清除策略,最基本的包含每個log文件多大,最多幾個log文件,log文件總大小達到多少時開始覆蓋之前的文件等,其實這些方面大神的源碼都考慮好了,直接用輪子更省心。

4. 冒煙測試

發布之前需對預發布版本進行主流程的測試,例如對于一個即時通信SDK需要測試普通消息互通、文件類消息互通、離線消息收取、apns推送正常、群消息正常等。


p.s. 本文提到的一些[命令]將在后面文章中單獨講一下。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容