ios 開發中 動態庫 與靜態庫的區別

來源:互聯網
上載者:User

標籤:

使用靜態庫的好處

1,模組化,分工合作

2,避免少量改動經常導致大量的重複編譯串連

3,也可以重用,注意不是共用使用

 

動態庫使用有如下好處:

1使用動態庫,可以將最終可執行檔體積縮小

2使用動態庫,多個應用程式共用記憶體中得同一份庫檔案,節省資源

3使用動態庫,可以不重新編譯串連可執行程式的前提下,更新動態庫檔案達到更新應用程式的目的。

從1可以得出,將整個應用程式分模組,團隊合作,進行分工,影響比較小。

等其他好處,

從2可以看出,其實動態庫應該叫共用庫,那麼從這個意義上來說,蘋果禁止iOS開發中使用動態庫就可以理解了:

因為在現在的iPhone,iPodTouch,iPad上面程式都是單進程的,也就是某一時刻只有一個進程在運行,那麼你寫個共用庫,

        ----共用給誰?(你使用的時候只有你一個應用程式存在,其他的應該被掛起了,即便是可以同時多個進程運行,別人能使用你的共用庫裡的東西嗎?你這個是給你自己的程式定製的。)

        ----目前蘋果的AppStore不支援模組更新,無法更新某個單獨檔案(除非自己寫一個更新機制:有自己的服務端放置最新動向庫檔案)

至於蘋果為啥禁止ios開發使用動態庫我就猜到上面倆原因

 

 

深入理解iPhone靜態庫

       在實際的編程過程中,通常會把一些公用函數製成函數庫,供其它程式使用,一則提搞了代碼的複用;二則提搞了核心技術的保密程度。所以在實際的項目開發中,經常會使用到函數庫,函數庫分為靜態庫和動態庫兩種。和多數人所熟悉的動態語言和靜態語言一樣,這裡的所謂靜態和動態是相對編譯期和運行期的:靜態庫在程式編譯時間會被連結到目標代碼中,程式運行時將不再需要改靜態庫;而動態庫在程式編譯時間並不會被連結到目標代碼中,只是在程式運行時才被載入,因為在程式運行期間還需要動態庫的存在。

  iPhone官方只支援靜態庫聯編。

深入理解framework(架構,其實相當於靜態架構,不是動態庫)

打包framework還是一個比較重要的功能,可以用來做一下事情:

(1)封裝功能模組,比如有比較成熟的功能模組封裝成一個包,然後以後自己或其他同事用起來比較方便。

(2)封裝項目,有時候會遇到這個情況,就是一家公司找了兩個開發公司做兩個項目,然後要求他們的項目中的一個嵌套進另一個項目,此時也可以把唄嵌套的項目打包成framework放進去,這樣比較方便。

 

我們為什麼需要架構(Framework)?

要想用一種開發人員友好的方式共用庫是很麻煩的。你不僅僅需要包含庫本身,還要加入所有的標頭檔,資源等等。

蘋果解決這個問題的方式是架構(framework)。基本上,這是含有固定結構並包含了引用該庫時所必需的所有東西的檔案夾。不幸的是,iOS禁止所有的動態庫。同時,蘋果也從Xcode中移除了建立靜態iOS架構的功能。

Xcode仍然可以支援建立架構的功能,重啟這個功能,我們需要對Xcode做一些小小的改動。

把代碼封裝在靜態架構是被app store所允許的。儘管形式不同,本質上它仍然是一種靜態庫。

架構(Framework)的類別

大部分架構都是動態連結程式庫的形式。因為只有蘋果才能在iOS裝置上安裝動態庫,所以我們無法建立這種類型的架構。

靜態連結庫和動態庫一樣,只不過它是在編譯時間連結二進位代碼,因此使用靜態庫不會有動態庫那樣的問題(即除了蘋果誰也不能在iOS上使用動態庫)。

“偽”架構是通過破解Xcode的目標Bundle(使用某些指令碼)來實現的。它在表面上以及使用時跟靜態架構並無區別。“偽”架構項目的功能幾乎和真實的架構項目沒有區別(不是全部)。

“嵌入”架構是靜態架構的一個封裝,以便Xcode能擷取架構內的資源(圖片、plist、nib等)。

本次發布包括了建立靜態架構和“偽”架構的模板,以及二者的“嵌入”架構。

用哪一種模板?

本次發布有兩個模板,每個模板都有“強”“弱”兩個類別。你可以選擇最適合一種(或者兩種都安裝上)。

最大的不同是Xcode不能建立“真”架構,除非你安裝靜態架構檔案xcspec在Xcode中。這真是一個遺憾(這個檔案是給項目使用的,而不是架構要用的)。

簡單第

簡單說,你可以這樣決定用哪一種模板:

  • 如果你不想修改Xcode,那麼請使用“偽”架構版本

  • 如果你只是想共用二進位(不是項目),兩種都可以

  • 如果你想把架構共用給不想修改Xcode的開發人員,使用“偽”架構版本

  • 如果你想把架構共用給修改過Xcode的開發人員,使用“真”架構版本

  • 如果你想把架構項目作為另一個項目的依賴(通過workspace或者子項目的方式),請使用“真”架構(或者“偽”架構,使用-framework——見後)

  • 如果你想在你的架構項目中加入其他靜態庫/架構,並把它們也連結到最終結果以便不需要單獨添加到使用者項目中,使用“偽”架構

“偽”架構

“偽”架構是破解的“reloacatable object file”(可重定位格式的目標檔案, 儲存著代碼和資料,適合於和其他的目標檔案串連到一起,用來建立一個可執行目標檔案或者是一個可共用目標檔案),它可以讓Xcode編譯出類似架構的東西——其實也是一個bundle。

“偽架構”模板把整個過程分為幾個步驟,用某些指令碼去產生一個真正的靜態架構(基於靜態庫而不是reloacatable object file)。而且,架構項目還是把它定義為wrapper.cfbundle類型,一種Xcode中的“二等公民”。

因此它跟“真”靜態架構一樣可以正常工作,但當存在依賴關係時就有麻煩了。

依賴問題

如果不使用依賴,只是建立普通的項目是沒有任何問題的。但是如果使用了項目依賴(比如在workspace中),Xcode就悲劇了。當你點擊“Link Binary With Libraries”下方的’+’按鈕時,“偽架構”無法顯示在列表中。你可以從你的“偽”架構項目的Products下面將它手動拖入,但當你編輯你的主專案時,會出現警告:

warning: skipping file ‘/somewhere/MyFramework.framework‘ (unexpectedfile type ‘wrapper.cfbundle‘ in Frameworks & Libraries build phase)

並伴隨“偽”架構中的連結錯誤。

幸運的是,有個辦法來解決它。你可以在”Other Linker Flags”中用”-framwork”開關手動告訴linker去使用你的架構進行連結:

-framework MyFramework

警告仍然存在,但起碼能正確連結了。

添加其他的庫/架構

如果你加入其他靜態(不是動態)庫/架構到你的“偽”架構項目中,它們將“連結”進你最終的二進位架構檔案中。在“真”架構項目中,它們是純引用,而不是連結。

你可以在項目中僅僅包含標頭檔而不是靜態庫/架構本身的方式避免這種情況(以便編譯通過)。

“真”架構

“真”架構各個方面都符合“真”的標準。它是真正的靜態架構,正如使用蘋果在從Xcode中去除的那個功能所建立的一樣。

為了能建立真正的靜態架構項目,你必需在Xcode中安裝一個xcspec檔案。

如果你發布一個“真”架構項目(而不是編譯),希望去編譯這個架構的人必需也安裝xcspec檔案(使用本次發布的安裝指令碼),以便Xcode能理解目標類型。

注意:如果你正在發布完全編譯的架構,而不是架構項目,終端使用者並不需要安裝任何東西。

我已經提交一個報告給蘋果,希望他們在Xcode中更新這個檔案,但那需要一點時間.OpenRadarlink here

加其他靜態庫/架構

如果你加入其他靜態(不是動態)庫/架構到你的“真”架構項目,它們只會被引用,而不會象“偽”架構一樣被連結到最終的二進位檔案中。

從早期版本升級

如果你是從Mk6或者更早的版本升級,同時使用“真”靜態架構,並且使用Xcode4.2.1以前的版本,請運行uninstall_legacy.sh以卸載早期用於Xcode的所有修正。然後再運行install.sh,重啟Xcode。如果你使用Xcode4.3以後,只需要運行install.sh並重啟Xcode。

安裝

分別運行Real Framework目錄或Fake Framework目錄下的install.sh指令碼進行安裝(或者兩個你都運行)。

重啟Xcode,你將在新項目嚮導的Framework&Library下看到StaticiOS Framework(或者Fake Static iOS Framework)。

卸載請運行unistall.sh指令碼並重啟Xcode。

建立一個iOS架構項目

  1. 建立新項目。

  2. 項目類型選擇Framework&Library下的Static iOS Framework(或者Fake Static iOS Framework)。

  3. 選擇“包含單元測試”(可選的)。

  4. 在target中加入類、資源等。

  5. 凡是其他項目要使用的標頭檔,必需聲明為public。進入target的Build Phases頁,展開Copy Headers項,把需要public的標頭檔從Project或Private部分拖拽到Public部分。

編譯你的 iOS 架構

  1. 選擇指定target的scheme

  2. 修改scheme的Run配置(可選)。Run配置預設使用Debug,但在準備部署的時候你可能想使用Release。

  3. 編譯架構(無論目標為iOS device和Simulator都會編譯出相同的二進位,因此選誰都無所謂了)。

  4. 從Products下選中你的framework,“show in Finder”。

在build目錄下有兩個檔案夾:(yourframework).framework and (your framework).embeddedframework.

如果你的架構只有代碼,沒有資源(比片、指令碼、xib、coredata的momd檔案等),你可以把(yourframework).framework 分發給你的使用者就行了。如果還包含有資源,你必需分發(your framework).embeddedframework給你的使用者。

為什麼需要embedded framework?因為Xcode不會尋找靜態架構中的資源,如果你分發(your framework).framework, 則架構中的所有資源都不會顯示,也不可用。

一個embedded framework只是一個framework之外的附加的包,包括了這個架構的所有資源的符號連結。這樣做的目的是讓Xcode能夠找到這些資源。

使用iOS 架構

iOS架構和常規的Mac OS動態架構差不多,只是它是靜態連結的而已。

在你的項目中使用一個架構,只需把它拖僅你的項目中。在包含標頭檔時,記住使用角括弧而不是雙引號括住架構名稱。例如,對於架構MyFramework:

#import <MyFramework/MyClass.h>

 

 

使用問題

Headers Not Found

如果Xcode找不到架構的標頭檔,你可能是忘記將它們聲明為public了。參考“建立一個iOS架構項目”第5步。

No Such Product Type

如果你沒有安裝iOS Universal Framework在Xcode,並企圖編譯一個universal架構項目(對於“真”架構,不是“假”架構),這會導致下列錯誤:

target specifies product type ‘com.apple.product-type.framework.static‘,but there‘s no such product type for the ‘iphonesimulator‘ platform

為了編譯“真”iOS靜態架構,Xcode需要做一些改動,因此為了編譯“真”靜態架構項目,請在所有的開發環境中安裝它(對於使用架構的使用者不需要,只有要編譯架構才需要)。

The selected run destination is not valid for this action

有時,Xcode出錯並載入了錯誤的active設定。首先,請嘗試重啟Xcode。如果錯誤繼續存在,Xcode產生了一個壞的項目(因為Xcode4的一個bug,任何類型的項目都會出現這個問題)。如果是這樣,你需要建立一個新項目重來一遍。

連結警告

第一次編譯架構target時,Xcdoe會在連結階段報告找不到檔案夾:

ld: warning: directory not found for option‘-L/Users/myself/Library/Developer/Xcode/DerivedData/MyFramework-ccahfoccjqiognaqraesrxdyqcne/Build/Products/Debug-iphoneos‘

此時,可以clean並重新編譯target,警告會消除。

Core Data momd not found

對於架構項目和應用程式項目,Xcode會以不同的方式編譯momd(託管物件模型檔案)。Xcode會簡單地在根目錄建立.mom檔案,而不會建立一個.momd目錄(目錄中包含VersionInfo.plist和.mom檔案)。

這意味著,當從一個embedded framework的model中執行個體化NSManagedObjectModel時,你必需使用.mom副檔名作為model的URL,而不是採用.momd副檔名。

NSURL *modelURL = [[NSBundle mainBundle]URLForResource:@"MyModel" withExtension:@"mom"];

Unknown class MyClass in Interface Builder file.

由於靜態架構採用靜態連結,linker會剔除所有它認為無用的代碼。不幸的是,linker不會檢查xib檔案,因此如果類是在xib中引用,而沒有在O-C代碼中引用,linker將從最終的可執行檔中刪除類。這是linker的問題,不是架構的問題(當你編譯一個靜態庫時也會發生這個問題)。蘋果內建架構不會發生這個問題,因為他們是運行時動態載入的,存在於iOS裝置韌體中的動態庫是不可能被刪除的。

有兩個解決的辦法:

 

     讓架構的終端使用者關閉linker的最佳化選項,通過在他們的項目的Other Linker Flags中添加-ObjC和-all_load。

     在架構的另一個類中加一個該類的代碼引用。例如,假設你有個MyTextField類,被linker剔除了。假設你還有一個MyViewController,它在xib中使用了MyTextField,MyViewController並沒有被剔除。你應該這樣做:

在MyTextField中:

+ (void)forceLinkerLoad_ {}

在MyViewController中:

+(void) initialize {     [MyTextField forceLinkerLoad_]; }

他們仍然需要添加-ObjC到linker設定,但不需要強制all_load了。

第2種方法需要你多做一點工作,但卻讓終端使用者避免在使用你的架構時關閉linker最佳化(關閉linker最佳化會導致object檔案膨脹)。

unexpected file type ‘wrapper.cfbundle‘ in Frameworks &Libraries build phase

這個問題發生在把“假”架構項目作為workspace的依賴,或者把它當作子項目時(“真”架構項目沒有這個問題)。儘管這種架構項目產生了正確的靜態架構,但Xcode只能從專案檔中看出這是一個bundle,因此它在檢查依賴性時發出一個警告,並在linker階段跳過它。

你可以手動添加一個命令讓linker在連結階段能正確連結。在依賴你的靜態架構的項目的OtherLinker Flags中加入:

-framework MyFramework

警告仍然存在, 但不會導致連結失敗。

Libraries being linked or not being linked into the finalframework

很不幸, “真”架構和“假”架構模板在處理引入的靜態庫/架構的工作方式不同的。

“真”架構模板採用正常的靜態庫產生步驟,不會連結其他靜態庫/架構到最終生產物中。

“假”架構模板採用“欺騙”Xcode的手段,讓它認為是在編譯一個可重定位格式的目標檔案,在連結階段就如同編譯一個可執行檔,把所有的靜態代碼檔案連結到最終產生物中(儘管不會檢查是否確實目標代碼)。為了實現象“真”架構一樣的效果,你可以只包含庫/架構的標頭檔到你的項目中,而不需要包含庫/架構本身。

Unrecognized selector in (some class with a category method)

如果你的靜態庫或靜態架構套件含了一個模組(只在類別代碼中聲明,沒有類實現),linker會搞不清楚,並把代碼從二進位檔案中剔除。因為在最終產生的檔案中沒有這個方法,所以當調用這個類別中定義的方法時,會報一個“unrecognizedselector”異常。

要解決這個,在包含這個類別的模組代碼中加一個“假的”類。linker發現存在完整的O-C類,會將類別代碼連結到模組。

我寫了一個標頭檔 LoadableCategory.h,以減輕這個工作量:

#import "SomeConcreteClass+MyAdditions.h"

#import "LoadableCategory.h"  MAKE_CATEGORIES_LOADABLE(SomeConcreteClass_MyAdditions);   @implementation SomeConcreteClass(MyAdditions)

  ... 

@end

在使用這個架構時,仍然還需要在Build Setting的Other Linker Flags中加入-ObjC。

執行任何代碼前單元測試崩潰

如果你在Xcode4.3中建立靜態架構(或庫)target時,勾選了“withunit tests”,當你試圖運行單元測試時,它會崩潰:

Thread 1: EXC_BAD_ACCESS (code=2, address=0x0) 0 0x00000000 --- 15 dyldbootstrap:start(...)

這是lldb中的一個bug。你可以用GDB來運行單元測試。編輯scheme,選擇Test,在Info標籤中將調試器Debugger從LLDB改為GDB。

ios 開發中 動態庫 與靜態庫的區別

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.