笔记@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是一种标准的目录结构,能够包含可执行程序,以及程序执行所需的资源文件。
  • bundle的作用在于规范代码及其资源的位置,便于系统访问。
  • .app / .bundle / .framework,这些都是bunle的后缀。
  • 缺少info.plist的bundle一样可以使用,但会失去某些特性。
  • 对于有info.plist的bundle来说,CFBundleDisplayName代表其在操作系统中的显示名,CFBundleName才是其真正意义上(代码所用)的名称。
Bundle和Package

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

  • 任意目录,如果Finder将其作为单独文件呈现给用户,那么这个目录就是一个package。
  • 用户可以通过右键--->Show Package Contents查看package的内容。
  • package的作用在于防止用户对于package作出修改,维护package的统一性。
  • 有些bundle也是package,例如application,因为用户可以通过Show Package Contents查看其内容;而有些不是,例如framework,它的内容可以直接查看。
  • iOS的.ipa解压缩后,就得到了一个bundle,也是一个package。
Bundle的类型
  • application
  • framework
  • loadable bundle / 含有可以载入的可执行文件,例如OS X的插件,iOS的widget
  • document package / 文档包
Bundle的创建
  • 通过xocde模版创建,applicaton / framework / loadable bundle都有自定特定的目录结构。

  • 通过shell脚本或手动创建目录结构。

    # 例子:通过脚本创建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 /
    可执行文件
    Info.plist
    app icon(如有)
    app启动图片(如有)
    storyboard / nib(如有)
    Settins.bundle(用于在系统设置中显示相关内容,如有)
    通用资源文件(同本地化资源相对,如音频,视频,数据库文件)
    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能够同时支持库的多个版本。
  • 静态库/动态库可以单独使用,也可以打包作为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可能包含可执行文件,也可能不包含。(虽然文档明确表示iOS不支持loadable bundle,但资源包类型的bundle也可以被使用)
MyLoadableBundle.bundle
    Contents/
        Info.plist
        MacOS/
            MyLoadableBundle // 可执行文件,资源包没有这个目录
        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是当前运行的可执行文件及其资源所在的bundle。

  • NSBundle的创建方式:

    • [NSBundle mainBundle]。
    • bundleWithPath: 根据绝对路径创建。
    • bundleWithIdentifier: 通过CFBundleIdentifier找到已经载入内存的bundle。
    • allFrameworks / allBundles: 返回相关的所有bundle。
    • bundleForClass: 某个类(的二进制文件)所在的bundle。
资源搜索模式

系统在bundle中搜索资源时,分为两步:

  1. 确定使用哪个本地化文件夹内的资源:

    • 根据系统的首选语言顺序寻找相应地本地化文件夹?.lproj
    • 如果没找到,则根据CFBundleDevelopmentRegion来确定选定本地化文件夹。
  2. 然后按照以下优先级搜索:

    1. 通用资源目录
    2. 特定地区资源目录
    3. 特定语言资源目录
    4. 开发语言资源目录
  • 注意,不会搜索上述目录下的二级目录,详见pathForResource:ofType:的文档。
  • 如果通用目录和特定语言目录有同名资源,则后者永远不会被找到。
根据iOS设备类型区分资源
  • 资源命名方式

    <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,即创建bundle对象。
    3. 从bundle中获取资源路径。注意,如果资源位于次级目录,则必须指明路径。
    4. 通过路径创建对象。
  • 例如,如下代码从app bundle根目录下的另一个bundle中获取一张图片。

- (void)viewDidLoad {
    [super viewDidLoad];

    // 1. 在main bundle中找到特定bundle
    NSString *sampleBundlePath = [[NSBundle mainBundle] pathForResource:@"SampleBundle.bundle" ofType:nil];
    // 2. 载入bundle,即创建bundle对象
    NSBundle *sampleBundle = [NSBundle bundleWithPath:sampleBundlePath];
    // 3. 从bundle中获取资源路径
    // 注意这里的图片位于通用资源目录下的Images二级目录,相对路径要明确这种关系
    NSString *pic1Path = [sampleBundle pathForResource:@"pic1.png" ofType:nil];
    // 4. 通过路径创建对象
    UIImage *image = [UIImage imageWithContentsOfFile:pic1Path];
    
}
如下代码从app bundle根目录下的另一个bundle中获取一张图片

通用资源目录

  • 所谓通用资源目录,起初我以为是由Info.plist中的CFBundlePackageType决定的,可能的类型包括:

    • APPL--->iOS应用
    • FMWK--->framework
    • BNDL--->lodable bundle
  • 但试着删除Info.plist后,系统依然遵循搜索模式,而非从bundle根目录开始搜索。

  • 接着,我试着打乱bundle下的目录顺序,例如将Contents和Resources目录删除,将所有资源文件任意放置,发现不论如何尝试,都无法使用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];
        // 根据路径创建图片
        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
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 这几天公司有一个新的需求,就是要将我们开发的某些东西都抽取出来,打个比方我们开发了A项目,可以以后B项目要包含A项...
    黄鱼儿啦啦啦阅读 6,091评论 2 16
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 框架捆绑 框架是封装动态共享库和支持该库所需的资源文件的分层目录。框架比典型的动态共享库提供了一些优势,因为它们为...
    nicedayCoco阅读 1,530评论 0 2
  • 如果你想将你开发的控件与别人分享,一种方法是直接提供源代码文件。然而,这种方法并不是很优雅。它会暴露所有的实现细节...
    小热狗阅读 3,400评论 3 9
  • (原文:How to Create a Framework for iOS作者:Sam Davies 译者:Mr_...
    Yaanco阅读 2,223评论 4 4