iOS基礎(chǔ)之Bundle詳解

在iOS工程中,如果我們使用xib來編寫視圖的話,會經(jīng)常用到Bundle.main.loadNibNamed的方法來加載視圖。那么Bundle到底是什么呢?除了main bundle還有其他bundle?
這篇文章是對Bundle的講解,主要說明Bundle的定義和特點(diǎn),Bundle的內(nèi)部結(jié)構(gòu)以及Bundle的基本使用。

1 Bundle的定義和特點(diǎn)

Bundle是一個含有可執(zhí)行的代碼及代碼所需資源,以特定標(biāo)準(zhǔn)的層次結(jié)構(gòu)組合起來的文件夾。這里的可執(zhí)行是指編譯過后可直接運(yùn)行的代碼程序。一個典型的例子就是iOS程序打包后的ipa,我們解壓ipa后會得到一個payload文件夾,進(jìn)入文件夾之后會發(fā)現(xiàn)一個和ipa名稱相同的.app文件加。這個.app文件夾就是一個Bundle。
系統(tǒng)如何識別Bundle呢?一般而言一個文件夾如果帶著.app,.bundle,.framework,.plugin,.kext等等特定后綴,那么系統(tǒng)就認(rèn)為是Bundle。如果使用Xcode創(chuàng)建項(xiàng)目的話,Xcode會提供相應(yīng)的模板來生成正確的Bundle類型。
從上面的后綴我們也可以看出Bundle主要分為:

  • Appliction。應(yīng)用程序,包含代碼和資源。iOS和macOS的app就是這種。
  • Frameworks??蚣埽瑒討B(tài)共享庫和相應(yīng)資源。我們常用的系統(tǒng)庫和第三方庫都屬于這種。
  • Plug-Ins。插件,macOS很多的系統(tǒng)功能支持插件,一種動態(tài)加載代碼模塊的方式。

使用Bundle可以很方便的管理程序的文件內(nèi)容,進(jìn)行本地化設(shè)置、程序移動和運(yùn)行等等。

2 Bundle的內(nèi)部結(jié)構(gòu)

2.1 iOS Application Bundle的結(jié)構(gòu)

Application類型的bundle是很常見的,一般里面會包含一下幾中類型的文件:

  • Info.plist文件。每個程序中必須有這個文件,因?yàn)樗顺绦蜻\(yùn)行的配置信息,是系統(tǒng)運(yùn)行程序的依據(jù)。
  • 可執(zhí)行代碼文件。這是程序的主體,包含了程序的進(jìn)入點(diǎn)和鏈接的靜態(tài)代碼。
  • 資源文件。程序運(yùn)行過程中需要的資源,比如圖片,音頻,視頻,多語言的字符串文件,nib文件,數(shù)據(jù)文件,配置文件等等。這里面的大部分文件都可以根據(jù)語言、地區(qū)、設(shè)備通過特定的結(jié)構(gòu)或命名方式加以區(qū)分,程序會自動識別加載。
  • 其他支持文件。Mac app可以嵌入高層資源,比如私有庫,插件,文件末班,自定義數(shù)據(jù)資源等等。iOS app可以包含自定義數(shù)據(jù)資源,但是不能包含私有庫和插件。

如果我們對于ipa中的.app文件夾右鍵顯示包內(nèi)容,我們可以看到app bundle的整體結(jié)構(gòu)如下:

MyApp  
  MyApp  //代碼編譯鏈接后的可執(zhí)行文件  
  Info.plist //程序信息
  Assets.car   //Assets中的資源對應(yīng)的文件。    
  MyAppIcon.png  //所有的icon圖片   
  LaunchImage.png  //所有啟動圖片 
  nibs  //工程中的xib,storyboard生成的nib文件 
  customResource  //工程目錄下或者更里層文件夾下的圖片,音、視頻,數(shù)據(jù)文件等自定義資源  
  customBundle.bundle  //工程中使用的其他第三方或資源的bundle  
  en.lproj  //語言區(qū)分的文件夾,可以使字符串、圖片,nib文件等
    MyString  
    MyImage
  zh-Hans.lproj  
    MyString  
    MyImage  
  PkgInfo  //系統(tǒng)識別信息  
  _CodeSignature  //簽名信息文件夾,里面的CodeResources包含對bundle中的所有資源文件的簽名信息  
  embedded.mobileprovision //打包的配置文件信息  

Assets.car無法直接打開,可以使用工具 cartool 列出包含的所有文件名稱。PkgInfo、簽名信息和嵌入配置文件都是打包后生成的,是系統(tǒng)驗(yàn)證app的依據(jù)。

2.2 Framework Bundle結(jié)構(gòu)

Framework Bundle和app bundle的最大不同在于框架庫有版本控制,因此必須包含版本列表和當(dāng)前版本信息。
Framework的bundle結(jié)構(gòu)如下:

MyFramework.framework/
    MyFramework -> Versions/Current/MyFramework  
    Resources   -> Versions/Current/Resources  
    Versions/
        A/
            MyFramework
            Headers/
                MyHeader.h
            Resources/ 
                Eglish.lproj/
                    InfoPlist.strings 
                Info.plist
        Current -> A

上面的根目錄下的MyFramework和Resources,以及Versions下面的current 都是文件引用,表明引用文件的位置。真正的代碼,資源,header等內(nèi)容都放在Versions文件夾下面的具體版本文件夾中,Current就指向當(dāng)前版本的引用。

關(guān)于多語言本地化文件,是按照language_region.lproj的格式命名的,比如en_GB表明英語英國,zh_Hans表示中文中國大陸。

3 Bundle的基本使用

使用bundle主要都是圍繞著定位資源路徑而來的。包括:獲取bundle及其信息(不管是main bundle還是其他bundle),獲取資源路徑(根據(jù)資源名稱和類型定位),使用系統(tǒng)API直接獲取資源(比如圖片、音頻、本地化字符串、context help,nibs,Info.plist內(nèi)容等等),具體使用可以參考 Class Bundle文檔,也可以參考我的Demo。

在磁盤上查找資源時,Bundle對象遵循特定的搜索模式。首先返回全局資源(即不在特定于語言的.lproj目錄中的資源),然后返回特定于區(qū)域和語言的資源。此搜索模式表示捆綁包按以下順序查找資源:

  • 全局(非本地化)資源
  • 特定于區(qū)域的本地化資源(基于用戶的區(qū)域首選項(xiàng))
  • 特定于語言的本地化資源(基于用戶的語言首選項(xiàng))
  • 開發(fā)語言資源(由bundle的Info.plist文件中的CFBundleDevelopmentRegion鍵指定)

由于全局資源優(yōu)先于特定于語言的資源,因此您不應(yīng)在應(yīng)用程序中同時包含給定資源的全局和本地化版本。存在資源的全局版本時,永遠(yuǎn)不會返回特定于語言的版本。這種優(yōu)先權(quán)的原因是性能。如果首先搜索本地化資源,則bundle對象可能會浪費(fèi)時間在返回全局資源之前搜索不存在的本地化資源。

在查找資源文件時,bundle對象在確定要返回的文件時會自動考慮許多標(biāo)準(zhǔn)文件名修飾符??梢詾樘囟ㄔO(shè)備(iphone,ipad)或特定屏幕分辨率(@2x,@ 3x)標(biāo)記資源。指定所需資源的名稱時,請不要包含這些修飾符。 bundle對象選擇最適合底層設(shè)備的文件。

參考資料:
1.Bundle Programming Guide
2.Class Bundle Reference

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容