iOS靜態庫SDK製作(包含第三方靜態庫)

leonlei發表於2017-12-14

前言

以下所涉及的框架和庫只針對iOS而言,不確保在其他平臺也適用。

最近由於公司業務需要,要求封裝一個支付SDK,需要用到微信支付和支付寶,之前做過的Framework沒有依賴其他第三方的庫所以比較好做,這次有所不同;一開始我想把支付寶和微信支付的SDK全部融合進來,折騰一天才發現我之前的想法有很多誤區,這樣是根本行不通的,不過最後還是封裝成功了,下面把我的經驗分享出來,供有需要的同學少走彎路。 製作之前最好把功課做足,看看靜態庫和動態庫到底是什麼東西。

轉載請註明出處:來自LeonLei的部落格http://www.gaoshilei.com

一. 靜態庫和動態庫的詳細介紹

我們平時的工程中或多或少都要引入第三方的SDK,就算你沒有引入第三方的,至少引用過系統的Framework吧?其實這些SDK和Framework都屬於庫,庫又分為靜態庫和動態庫,我們平時匯入的第三方SDK有的是Framework,有的是.a,到底哪些是動態庫,哪些是靜態庫呢?下面分別介紹靜態庫、動態庫,Framework和.a以及.dylib/.tbd區別

一. 靜態庫與動態庫

首先要解釋一下什麼是庫,庫(Library)其實就是一段編譯好的二進位制程式碼,加上標頭檔案就可以供別人使用,一般會有兩種情況要用到庫:

  • 某些程式碼需要給別人使用,但是我們不希望別人看到原始碼,就需要以庫的形式進行封裝,只暴露出標頭檔案。
  • 對於某些不會進行大的改動的程式碼,比方說很多大公司常用且很少變動的模組都會編譯成庫,這樣做的好處一是可以節省編譯時間,二來對於程式碼的管理也非常方便。

因為庫是已經編譯好的二進位制檔案了,編譯的時候只需要link一下,既然提到了link那就有不同的形式了,靜態和動態,與之相對應的就是靜態庫和動態庫

1. 靜態庫

平時我們用的第三方SDK基本上都是靜態庫,靜態庫的幾個特點:

  • 在App專案編譯的時候會被拷貝一份編譯到目標程式中,相當於將靜態庫嵌入了,所以得到的App二進位制檔案會變大。
  • 在使用的時候,需要手動匯入靜態庫所依賴的其他類庫。(比如說某個SDK中使用到了CoreMotion.framework,在使用的時候需要手動匯入。有的SDK需要link十幾個系統庫,這個時候非常噁心,只能一個一個手動加,這是靜態庫一個很大的不便之處。)
  • 匯入靜態庫的應用可以減少對外界的依賴,如果匯入的是第三方動態庫,動態庫找不到的話應用就會崩掉,例如Linux上經常出現的lib not found。
  • 靜態庫很大的一個優點是減少耦合性,因為靜態庫中是不可以包含其他靜態庫的,使用的時候要另外匯入它的依賴庫,最大限度的保證了每一個靜態庫都是獨立的,不會重複引用。

2. 動態庫

這個是我們最常用的一類庫,使用頻率最高的UIKit.framework和Fundation.framework都屬於動態庫,所有.dylib和.tbd結尾的都屬於動態庫。動態庫的幾個特點:

  • 平時使用的系統庫都放在iOS系統中,在你打包應用程式的時候這些庫不會拷貝到你的程式中,當需要使用的時候會動態從iOS系統中載入它們,因為這個原因,動態庫也被稱作共享庫。編譯時才載入的特性,也可以讓我們隨時對庫進行替換,而不需要重新編譯程式碼。
  • 這些庫是所有應用公用的,換一種說法就是節省了應用安裝包的體積,這是區別靜態庫很重要的一個特點,因為靜態庫使用一次就要拷貝一次,非常浪費資源。
  • 動態庫在製作的時候可以直接包含靜態庫,也能自動link所需要的依賴庫。
  • 使用動態庫的時候不需要再次link依賴庫,即導即用,這個就厲害了。唯一需要注意的是在匯入自己製作的動態庫時,需要在Embedded Binaries中匯入,不然會報錯:image not found。此時這個動態庫會跟靜態庫一樣被拷貝到目標程式中進行編譯,蘋果又把這種Framework叫做Embedded Framework

關於動態庫要搞清楚一點,我們自己製作的動態庫與系統動態庫的區別,我們自己製作的動態庫引入App專案的時候需要embed進專案,也就是要拷貝到目標程式中,這就有點不像動態庫的特性了,蘋果這麼做也是考慮安全問題吧!
至於能不能正常上架,我也不清楚,查了大量資料都是抄來抄去沒說清楚,我猜測是不能上架的,因為一般的第三方SDK也都是靜態庫的形式,我猜測一個重要原因是iOS的應用本來就是執行在沙盒裡面的,不同應用之間不能共享程式碼,同時動態下載程式碼蘋果肯定也是明令禁止的,所以動態庫也就失去意義了。當然可能還有其他因素,歡迎交流學習!

二. Framework、.a、.dylib/.tbd

1. Framework

Framework的英文釋意是框架,主要由Headers、binary檔案、.bundle這三部分構成,除此之外還有Info.plist和Modules,後兩者主要記錄Framework的版本之類的資訊,一般都會刪掉,不做討論

  • Headers
    包含我們在製作Framework的時候暴露的標頭檔案,所有被暴露的.h都放在這裡。
  • binary檔案
    整個Framework的核心,所有程式碼都被編譯成了這樣一坨二進位制檔案,這裡要注意的是新增的依賴庫不會被編譯進來,用的時候還需要重新link其他依賴庫。
  • .bundle
    資原始檔都打包放在這裡。在製作Framework的時候不可以把圖片直接放在專案中,否則製作好之後圖片是一張一張的出現在專案中非常亂,需要新建一個bundle將圖片放進去,這裡的bundle提供整個SDK的圖片資源。
    **注意:**圖片放進bundle之後不可以用[UIImage ImageWithName:]讀取圖片。要先找到bundle包再拿圖片。

這裡要糾正一個誤區

很多人認為系統的Framework就是動態庫,我們自己製作的Framework就是靜態庫。

其實Framework既可以是靜態庫也可以是動態庫,這取決於編譯成的Mach-O(就是那個二進位制檔案)是動態庫還是靜態庫,Framework本質上並不是一個庫,它是蘋果為了方便開發者提供了一種庫的打包方式,Framework會將Mach-O檔案、標頭檔案和資源包全都包含進來,不需要你再手動整理,我們也可以通過Xcode來製作framework動態庫使用。 所以總結: Framework是庫的打包形式,既可以是動態庫也是靜態庫。

2. .a靜態庫

這類靜態庫與Framework基本類似,不同的是在打包成.a檔案的同時,還需要提供標頭檔案,使用時相較於Framework比較麻煩,(例如微信支付SDK使用的是.a,不同的是支付寶SDK是以framework的形式打包的)。.a這樣打包不夠方便,而Framework編譯完成暴露的標頭檔案都已經放好了。

3. .dylib/.tbd 動態庫

這類動態庫我們也經常用,基本上都是系統提供的,一般不能自己製作,就算你通過其他方式製作使用,也肯定不能上架的,這裡沒什麼好講的。

二. Framework的製作

動態庫與靜態庫的製作流程基本一樣,包括標頭檔案的暴露等,唯一不同的是Mach-O檔案的編譯形式。本節將介紹Xcode製作Framework的過程,本次製作的Framework靜態庫依賴其他第三方靜態庫(Framework和.a)。

1> 新建工程

新建Framework工程

這裡要選Framework,如果選擇右邊的Static Library製作出來的是.a靜態庫。

2> 匯入所有要打包的檔案和其他第三方靜態庫
正常匯入要打包的檔案就可以了,在匯入第三方靜態庫的時候要注意,不要選擇新增到target中,如果新增進去要去target裡面把第三方靜態庫刪掉(只需匯入,不要新增進target)

匯入第三方靜態庫

匯入第三方靜態庫之後再link依賴的系統庫,像這樣
link依賴庫

注意上面的執行目標,因為我用的是Xcode8,最低支援到iOS8。
要打包的檔案和第三方靜態庫全部匯入完成
所有檔案匯入情況

3> 專案性質修改
把專案的membership需改為public,否則標頭檔案暴露將會不正常

修改專案的membership

4> 暴露標頭檔案
將標頭檔案暴露出去,供外界使用,所有的編譯檔案都在Project中,需要右擊新增到public裡面

暴露標頭檔案

5> 選擇Mach-O的編譯方式
這是最重要的一步,這一步決定我們製作出來的是靜態庫還是動態庫,預設選擇的是Dynamic Library,要手動選擇Static Library

Mach-O 形式

6> 編譯
如果你的依賴庫裡面有lib開頭的dylib動態庫,此時應該會報錯

動態庫連結報錯

什麼意思呢?大概就是沒找到對應的庫檔案,因為tbd是蘋果提供的新的動態庫格式,之前都是dylib,不知道這裡又抽什麼風,下面解決問題。

7> tbd動態庫報錯修改
先把原來的.tbd刪掉,然後再次新增,這個時候選擇add other,在彈出的視窗中按快捷鍵shift + command + G 調出finder的前往視窗,輸入/usr/lib,然後新增相應的dylib動態庫

修改的動態庫

替換完成之後重新編譯專案,生成Framework(可在Product檔案中右擊在finder中顯示找到)

8> 使用
新建一個資料夾,將製作好的靜態庫拷貝出來放進去,再將第三方靜態庫拷貝到相同的資料夾中,此時只要將這個資料夾提供給外界使用就可以了,這是我寫的測試demo驗證打包好的SDK是否可以正常使用

製作完成使用

至此我們已經完成了Framework中包含其他第三方靜態庫的製作。
如果需要製作動態庫,只需要在第5步中將Mach-O的形式改為Dynamic Library就可以了,其他步驟一樣

如果有問題請在留言區留言,或者郵件給我,互相交流學習!

相關文章