筆記@Bundle Programming Guide

筆記@Bundle Programming Guide


概覽

A bundle is a directory with a standardized hierarchical structure that holds executable code and the
resources used by that code.

  • bundle是一種標準的目錄結構,能夠包含可執(zhí)行程序,以及程序執(zhí)行所需的資源文件。
  • bundle的作用在于規(guī)范代碼及其資源的位置,便于系統(tǒng)訪問。
  • .app / .bundle / .framework,這些都是bunle的后綴。
  • 缺少info.plist的bundle一樣可以使用,但會失去某些特性。
  • 對于有info.plist的bundle來說,CFBundleDisplayName代表其在操作系統(tǒng)中的顯示名,CFBundleName才是其真正意義上(代碼所用)的名稱。
Bundle和Package

A package is any directory that the Finder presents to the user as if it were a single file.

  • 任意目錄,如果Finder將其作為單獨文件呈現(xiàn)給用戶,那么這個目錄就是一個package。
  • 用戶可以通過右鍵--->Show Package Contents查看package的內容。
  • package的作用在于防止用戶對于package作出修改,維護package的統(tǒng)一性。
  • 有些bundle也是package,例如application,因為用戶可以通過Show Package Contents查看其內容;而有些不是,例如framework,它的內容可以直接查看。
  • iOS的.ipa解壓縮后,就得到了一個bundle,也是一個package。
Bundle的類型
  • application
  • framework
  • loadable bundle / 含有可以載入的可執(zhí)行文件,例如OS X的插件,iOS的widget
  • document package / 文檔包
Bundle的創(chuàng)建
  • 通過xocde模版創(chuàng)建,applicaton / framework / loadable bundle都有自定特定的目錄結構。

  • 通過shell腳本或手動創(chuàng)建目錄結構。

    # 例子:通過腳本創(chuàng)建framework目錄結構
    set -e
    
    export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"
    
    # Create the path to the real Headers dir
    mkdir -p "${FRAMEWORK_LOCN}/Versions/A/Headers"
    
    # Create the required symlinks
    /bin/ln -sfh A "${FRAMEWORK_LOCN}/Versions/Current"
    /bin/ln -sfh Versions/Current/Headers "${FRAMEWORK_LOCN}/Headers"
    /bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" \
    "${FRAMEWORK_LOCN}/${PRODUCT_NAME}"
    
    # Copy the public headers into the framework
    /bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \
    "${FRAMEWORK_LOCN}/Versions/A/Headers"
    

Bundle結構

iOS Bundle結構
app bundle /
    可執(zhí)行文件
    Info.plist
    app icon(如有)
    app啟動圖片(如有)
    storyboard / nib(如有)
    Settins.bundle(用于在系統(tǒng)設置中顯示相關內容,如有)
    通用資源文件(同本地化資源相對,如音頻,視頻,數據庫文件)
    en.lproj...(本地化資源目錄)
  • 注意,iOS app的通用資源都放在的bundle的根目錄下。
framework結構

The structure for frameworks is based on a bundle format that predates OS X and supports the inclusion of multiple versions of the framework’s code and resources in the framework bundle.

  • framework的bundle結構不同于app,一個framework能夠同時支持庫的多個版本。
  • 靜態(tài)庫/動態(tài)庫可以單獨使用,也可以打包作為framework使用。
  • framework不一定要包含庫所暴露的頭文件,但包含了用起來就會很方便。
MyFramework.framework/
    MyFramework->Versions/Current/MyFramework // 指向最新版本
    Resources->Versions/Current/Resources // 指向最新版本
    Versions/
        Current->A // 指向最新版本
        A/
            MyFramework
            Info.plist
            Headers/
                MyHeaders.h
            Resources/
                English.lproj/
                    InfoPlist.strings
  • 注意,framework的通用資源放在Resources目錄下。

The bundle’s Versions subdirectory contains the individual framework revisions while symbolic links at the top of the bundle directory point to the latest revision.

  • 跟目錄下的子目錄Versions包含庫的各個版本,而根目錄下的鏈接都指向這個字目錄下的最新版本的相關內容。
Loadable Bundle
  • OS X的plugin / widget都屬于loadable bundle;用于打包資源的bundle也屬于此列;所以,這種bundle可能包含可執(zhí)行文件,也可能不包含。(雖然文檔明確表示iOS不支持loadable bundle,但資源包類型的bundle也可以被使用)
MyLoadableBundle.bundle
    Contents/
        Info.plist
        MacOS/
            MyLoadableBundle // 可執(zhí)行文件,資源包沒有這個目錄
        Resources/
            Pic.jpg
            Beauty.png
            en.lproj/
                MyLoadableBundle.nib
                InfoPlist.strings
            jp.lproj/
                MyLoadableBundle.nib
                InfoPlist.strings

  • 其結構同OS X應用bundle基本一致。
  • 注意,通用資源放在Resources目錄下。
Document Package
  • 沒看

訪問Bundle內容

Bundle對象

The main bundle is the bundle that contains the code and resources for the running application.

  • main bundle是當前運行的可執(zhí)行文件及其資源所在的bundle。

  • NSBundle的創(chuàng)建方式:

    • [NSBundle mainBundle]。
    • bundleWithPath: 根據絕對路徑創(chuàng)建。
    • bundleWithIdentifier: 通過CFBundleIdentifier找到已經載入內存的bundle。
    • allFrameworks / allBundles: 返回相關的所有bundle。
    • bundleForClass: 某個類(的二進制文件)所在的bundle。
資源搜索模式

系統(tǒng)在bundle中搜索資源時,分為兩步:

  1. 確定使用哪個本地化文件夾內的資源:

    • 根據系統(tǒng)的首選語言順序尋找相應地本地化文件夾?.lproj;
    • 如果沒找到,則根據CFBundleDevelopmentRegion來確定選定本地化文件夾。
  2. 然后按照以下優(yōu)先級搜索:

    1. 通用資源目錄
    2. 特定地區(qū)資源目錄
    3. 特定語言資源目錄
    4. 開發(fā)語言資源目錄
  • 注意,不會搜索上述目錄下的二級目錄,詳見pathForResource:ofType:的文檔。
  • 如果通用目錄和特定語言目錄有同名資源,則后者永遠不會被找到。
根據iOS設備類型區(qū)分資源
  • 資源命名方式

    <basename> <device> .<filename_extension> 
    
  • basename: 用來在代碼中訪問資源文件

  • filename_extension: 文件類型擴展名

  • device: ~ipad / ~iphone

  • 例子

    // MyImage~ipad.png  / MyImage~iphone.png 
    UIImage* anImage = [UIImage imageNamed:@"MyImage.png"];
    

從其他Bundle中加載資源

  • 從main bundle中其他bundle加載資源,可以分為四步:

    1. 在main bundle中找到特定bundle。
    2. 載入bundle,即創(chuàng)建bundle對象。
    3. 從bundle中獲取資源路徑。注意,如果資源位于次級目錄,則必須指明路徑。
    4. 通過路徑創(chuàng)建對象。
  • 例如,如下代碼從app bundle根目錄下的另一個bundle中獲取一張圖片。

- (void)viewDidLoad {
    [super viewDidLoad];

    // 1. 在main bundle中找到特定bundle
    NSString *sampleBundlePath = [[NSBundle mainBundle] pathForResource:@"SampleBundle.bundle" ofType:nil];
    // 2. 載入bundle,即創(chuàng)建bundle對象
    NSBundle *sampleBundle = [NSBundle bundleWithPath:sampleBundlePath];
    // 3. 從bundle中獲取資源路徑
    // 注意這里的圖片位于通用資源目錄下的Images二級目錄,相對路徑要明確這種關系
    NSString *pic1Path = [sampleBundle pathForResource:@"pic1.png" ofType:nil];
    // 4. 通過路徑創(chuàng)建對象
    UIImage *image = [UIImage imageWithContentsOfFile:pic1Path];
    
}
如下代碼從app bundle根目錄下的另一個bundle中獲取一張圖片

通用資源目錄

  • 所謂通用資源目錄,起初我以為是由Info.plist中的CFBundlePackageType決定的,可能的類型包括:

    • APPL--->iOS應用
    • FMWK--->framework
    • BNDL--->lodable bundle
  • 但試著刪除Info.plist后,系統(tǒng)依然遵循搜索模式,而非從bundle根目錄開始搜索。

  • 接著,我試著打亂bundle下的目錄順序,例如將Contents和Resources目錄刪除,將所有資源文件任意放置,發(fā)現(xiàn)不論如何嘗試,都無法使用pathForResource:ofType:找到資源。

  • 最后,通拼接bundle路徑+資源路徑的方式,找到了資源。代碼如下:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // bundle路徑
        NSString *sampleBundlePath = [[NSBundle mainBundle] pathForResource:@"AlipaySDK.bundle" ofType:nil];
        // 拼接資源路徑,bar.png放置于bundle根目錄下
        NSString *pic1Path = [NSString stringWithFormat:@"%@/bar.png", sampleBundlePath];
        // 根據路徑創(chuàng)建圖片
        UIImage *image = [UIImage imageWithContentsOfFile:pic1Path];
    }
    

拾遺

  • 決定哪些資源文件應該加入bundle

    選定target--->Build Phases--->Copy Bundle Resources: 選擇需要加入的資源文件
    // 如果需要保留目錄結構,則應將資源文件連同文件夾一起拖入項目,并選中Added Folders項下的Create folder references
    
  • 本地化目錄命名方式

    language_region.lproj // 其中,_region可以不要
    

If you used custom subdirectories in your bundle to organize resource files, you can speed up the search by providing the name of the subdirectory that contains the desired file.

  • 如果要從bundle中的某個次級目錄搜索資源,那么必須指定這個次級目錄的路徑,否則可能找不到。

    // Posters是bundle中的二級目錄
    UIImage* anImage = [UIImage imageNamed:@"Posters/MyImage.png"];
    
  • iOS app的生成過程:

    build App Target--->app bundle--->.ipa
    
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 這幾天公司有一個新的需求,就是要將我們開發(fā)的某些東西都抽取出來,打個比方我們開發(fā)了A項目,可以以后B項目要包含A項...
    黃魚兒啦啦啦閱讀 6,408評論 2 16
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,641評論 19 139
  • 框架捆綁 框架是封裝動態(tài)共享庫和支持該庫所需的資源文件的分層目錄??蚣鼙鹊湫偷膭討B(tài)共享庫提供了一些優(yōu)勢,因為它們?yōu)?..
    nicedayCoco閱讀 1,810評論 0 2
  • 如果你想將你開發(fā)的控件與別人分享,一種方法是直接提供源代碼文件。然而,這種方法并不是很優(yōu)雅。它會暴露所有的實現(xiàn)細節(jié)...
    小熱狗閱讀 3,615評論 3 9
  • (原文:How to Create a Framework for iOS作者:Sam Davies 譯者:Mr_...
    Yaanco閱讀 2,477評論 4 5

友情鏈接更多精彩內容