iOS中的靜態庫與動態庫,區別、制作和使用

jw789520 8年前發布 | 8K 次閱讀 動態庫 iOS開發 移動開發

如果我們有些功能要給別人用,但是又不想公開代碼實現,比如高德地圖、第三方登錄分享等等,這時候我們就要打包成庫了。庫分靜態庫和動態庫兩種:

靜態庫:以 .a 和 .framework 為文件后綴名。

動態庫:以 .tbd (之前叫 .dylib ) 和 .framework 為文件后綴名。

靜態庫與動態庫的區別

靜態庫:鏈接時會被完整的復制到可執行文件中,被多次使用就有多份拷貝。

動態庫:鏈接時不復制,程序運行時由系統動態加載到內存,系統只加載一次,多個程序共用(如系統的 UIKit.framework 等),節省內存。

但是蘋果不讓使用自己的動態庫,否則審核就無法通過。

我們先來看一下iOS設備有哪些架構,因為下面要用到:

模擬器:

iPhone4s-iPnone5:i386

iPhone5s-iPhone7 Plus:x86_64

真機:

iPhone3gs-iPhone4s:armv7

iPhone5-iPhone5c:armv7s

iPhone5s-iPhone6s:Plus:arm64

支持armv7的靜態庫可以在armv7s上正常運行。

.a靜態庫的制作

1、先創建一個新的Xcode工程Test,需要選擇下面這個模板:

選擇模板

創建完成后是這個樣子的:

創建工程

2、我們把默認生成的Test.h和Test.m刪掉,重新創建一個類PrintString,在這個類里面添加一個單純打印字符串的簡單方法:

PrintString.h

PrintString.m

3、選擇添加公開頭文件

為了讓使用者知道有哪些方法可以用,我們需要公開頭文件,這里我們公開PrintString.h:

選擇添加公開頭文件

4、修改配置

我們需要把 Build Active Architecture Only 修改為NO,否則生成的靜態庫就只支持當前選擇設備的架構。

修改配置

5、然后編譯

我們分別選擇 Generic iOS Device 和 任意一個模擬器 各編譯一次,編譯完后,我們會看到工程中Products文件夾下的libTest.a由紅色變成了黑色,然后 show in finder ,看看生成的文件:

Untitled.gif

我們看到它為真機和模擬器都生成了.a靜態庫。里面都包含我們選擇公開的頭文件。

我們來看看靜態庫支持的框架:命令為 lipo -info 靜態庫名字

查看靜態庫支持的框架

我們看到, Debug-iphoneos 里面的靜態庫支持的架構有 armv7 和 arm64 所以它只能用于真機,在模擬器上會報錯。 Debug-iphonesimulator 里面的靜態庫支持的架構有 i386 和 x86_64 ,所以它只能用于模擬器,在真機上會報錯。

如果想要讓模擬器和真機通用一個靜態庫,我們可以使用終端命令來實現。命令格式: lipo -create 第一個.a文件的絕對路徑 第二個.a文件的絕對路徑 -output 最終的.a文件路徑 :

生成通用靜態庫

我們看到生成了一個新的 libTest.a 文件。這個靜態庫就支持所有模擬器和所有真機了。然后我們創建一個文件夾,把.a和頭文件都放進去,我們最終需要使用的就是這個文件夾:

新建文件夾

注意:為了開發方便,我們可以使用生成的通用靜態庫,但是最終上線的使用我們可以只導入真機的,這樣工程的體積也會小一些。

使用生成的.a靜態庫

新建一個工程,將上面的通用靜態庫拖進去,導入頭文件,就可以使用里面的方法了。經過試驗,我們生成的靜態庫在真機上和模擬器上都能成功打印字符串:

Paste_Image.png

.frameworke靜態庫的制作

1、先創建一個新的Xcode工程LibTest,需要選擇下面這個模板:

選擇模板

創建完成后是這個樣子的:

創建完成

創建完成后我們可以看到,工程本身自帶一個 LibTest.h 文件和一個 Info.plist 文件。

2、我們創建一個類 PrintString ,添加一個單純打印字符串的簡單方法:

PrintString.h

PrintString

3、選擇添加公開頭文件

為了讓使用者知道有哪些方法可以用,我們需要公開頭文件,我們需要在 并且將 Target->Build Phases->Headers 中的 Projec t中要暴露的頭文件拖拽到 Pulic 里面,這里我們公開 PrintString.h :

選擇添加公開頭文件

注意:暴露出來的頭文件中import的其他類也得添加到public中暴露出來。如果不想將import的類暴露出來,那么在頭文件中用@class 然后在對應的.m文件中再import。

4、設置支持所有架構(和.a制作一樣)

5、修改生成的 Mach-O 格式,因為動態庫也可以是以framework形式存在,所以需要設置,否則默認打出來的是動態庫。將 target->BuildSetting->Mach-o Type 設為 Static Library (默認為 Dynamic Library ):

修改生成的Mach-O格式

6、編譯

我們分別選擇 Generic iOS Device 和 任意一個模擬器 各編譯一次,編譯完后,我們會看到工程中Products文件夾下的LibTest.framework由紅色變成了黑色,然后 show in finder ,看看生成的文件:

編譯

我們看到它為真機和模擬器都生成了LibTest.framework靜態庫。

我們來查看靜態庫支持的框架:與上面不同,命令為 lipo -info framework下的二進制文件名字

查看靜態庫支持的框架

如果想要讓模擬器和真機通用一個靜態庫,我們可以使用終端命令來實現。合并的命令與上面不同的是:framework靜態庫合并的不是framework,而是framework下的二進制文件,命令為:

lipo -create 第一個framework下二進制文件的絕對路徑 第二個framework下二進制文件的絕對路徑 -output 最終的二進制文件路徑 :

合并二進制文件

然后將任何一個framework中的二進制文件替換成合并后的二進制文件,然后把framework添加到要使用的項目中即可使用。

使用生成的.framework靜態庫

新建一個工程,將靜態庫拖進去,導入頭文件,就可以使用里面的方法了。經過試驗,我們生成的靜態庫在真機上和模擬器上都能成功打印字符串:

Paste_Image.png

注意:

如果靜態庫中有category類,則在使用靜態庫的項目配置中 Other Linker Flags 需要添加參數 -ObjC 或者 -all_load 。

如果創建的framework類中使用了 .tbd ,則需要在實際項目中導入 .tbd 動態庫。

運行調試靜態庫

如果你是開發靜態庫的人,你會發現上面的方法只是制作靜態庫,并沒有辦法運行看效果和調試bug,這時候我們可以這樣:

1、新建一個專門用來開發靜態庫的正常工程Test:

新建工程

建好的工程

2、添加一個靜態庫的target

添加一個靜態庫的target

我們看到它生成了幾樣東西:

一個framework的target:在這里面修改靜態庫的配置們,例如支持的架構、要暴露的頭文件們和Mach-O的配置。

一個LibTest文件夾:靜態庫里面的類們都放在這里面。

product文件夾下面的LibTest.framework:在這里show in finder找到編譯后生成的靜態庫。

3、開發調試代碼

開發調試代碼

我們看到程序可以正常運行,并可以在動態庫里面蹲點運行。方便我們調試。

4、確保代碼沒問題后,選擇對應的target編譯生成。

編譯生成

5、后面的過程就與上面一樣了。

 

來自:http://ios.jobbole.com/90470/

 

 本文由用戶 jw789520 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!