iOS中的靜態庫與動態庫,區別、製做和使用

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

靜態庫:以.a 和 .framework爲文件後綴名。
動態庫:以.tbd(以前叫.dylib) 和 .framework 爲文件後綴名。架構

靜態庫與動態庫的區別框架

靜態庫:連接時會被完整的複製到可執行文件中,被屢次使用就有多份拷貝。
動態庫:連接時不復制,程序運行時由系統動態加載到內存,系統只加載一次,多個程序共用(如系統的UIKit.framework等),節省內存。iphone

可是蘋果不讓使用本身的動態庫,不然審覈就沒法經過。ui

咱們先來看一下iOS設備有哪些架構,由於下面要用到:.net

模擬器:
iPhone4s-iPnone5:i386
iPhone5s-iPhone7 Plus:x86_64調試

真機:
iPhone3gs-iPhone4s:armv7
iPhone5-iPhone5c:armv7s
iPhone5s-iPhone7 Plus:arm64code

支持armv7的靜態庫能夠在armv7s上正常運行。blog

.a靜態庫的製做ip

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


 


建立完成後是這個樣子的:


 

二、咱們把默認生成的Test.h和Test.m刪掉,從新建立一個類PrintString,在這個類裏面添加一個單純打印字符串的簡單方法:


 


 

三、選擇添加公開頭文件
爲了讓使用者知道有哪些方法能夠用,咱們須要公開頭文件,這裏咱們公開PrintString.h:


 

四、修改配置
咱們須要把Build Active Architecture Only修改成NO,不然生成的靜態庫就只支持當前選擇設備的架構。


 

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


 

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

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


 

咱們看到,Debug-iphoneos裏面的靜態庫支持的架構有armv7arm64因此它只能用於真機,在模擬器上會報錯。Debug-iphonesimulator裏面的靜態庫支持的架構有i386x86_64,因此它只能用於模擬器,在真機上會報錯。

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


 

咱們看到生成了一個新的libTest.a文件。這個靜態庫就支持全部模擬器和全部真機了。而後咱們建立一個文件夾,把.a和頭文件都放進去,咱們最終須要使用的就是這個文件夾:


 

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

使用生成的.a靜態庫

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


 

.frameworke靜態庫的製做

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


 


建立完成後是這個樣子的:


 

建立完成後咱們能夠看到,工程自己自帶一個LibTest.h文件和一個Info.plist文件。

二、咱們建立一個類PrintString,添加一個單純打印字符串的簡單方法:


 

三、選擇添加公開頭文件
爲了讓使用者知道有哪些方法能夠用,咱們須要公開頭文件,咱們須要在 而且將Target->Build Phases->Headers中的Project中要暴露的頭文件拖拽到Pulic裏面,這裏咱們公開PrintString.h

 

注意:暴露出來的頭文件中import的其餘類也得添加到public中暴露出來。若是不想將import的類暴露出來,那麼在頭文件中用@class 而後在對應的.m文件中再import。

四、設置支持全部架構(和.a製做同樣)
五、修改生成的Mach-O格式,由於動態庫也能夠是以framework形式存在,因此須要設置,不然默認打出來的是動態庫。將target->BuildSetting->Mach-o Type設爲Static Library(默認爲Dynamic Library):

 

六、編譯
咱們分別選擇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靜態庫

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

 

注意:
若是靜態庫中有category類,則在使用靜態庫的項目配置中Other Linker Flags須要添加參數-ObjC或者-all_load
若是建立的framework類中使用了.tbd,則須要在實際項目中導入.tbd動態庫。

運行調試靜態庫

若是你是開發靜態庫的人,你會發現上面的方法只是製做靜態庫,並無辦法運行看效果和調試bug,這時候咱們能夠這樣:
一、新建一個專門用來開發靜態庫的正常工程Test:

 

 

二、添加一個靜態庫的target

 

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

一個framework的target:在這裏面修改靜態庫的配置們,例如支持的架構、要暴露的頭文件們和Mach-O的配置。
一個LibTest文件夾:靜態庫裏面的類們都放在這裏面。
product文件夾下面的LibTest.framework:在這裏show in finder找到編譯後生成的靜態庫。

三、開發調試代碼

1608265-f4ac760cb598db22.gif

 

咱們看到程序能夠正常運行,並能夠在動態庫裏面蹲點運行。方便咱們調試。

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

 

五、後面的過程就與上面同樣了

 

 

 

原文:http://bbs.520it.com/forum.php?mod=viewthread&tid=2884&page=&extra=#pid31800

相關文章
相關標籤/搜索