Bundle 文件,简单理解,就是资源文件包。我们将许多图片、XIB、文本文件组织在一起,打包成一个 Bundle 文件。方便在其他项目中引用包内的资源。
Bundle 文件是静态的,也就是说,我们包含到包中的资源文件作为一个资源包是不参加项目编译的。也就意味着,bundle 包中不能包含可执行的文件。它仅仅是作为资源,被解析成为特定的 2 进制数据。
版本
真机-Debug版本
真机-Release版本
模拟器-Debug版本
模拟器-Release版本
Debug
含完整的符号信息,以方便调试
不会对代码进行优化
Release
不会包含完整的符号信息
的执行代码是进行过优化的
的大小会比Debug版本的略小
在执行速度方面,Release版本会更快些(但不意味着会有显著的提升)
SourcesBundle例子和SDKDemoBundle例子
1.sdk 中xib,图片等一切资源都需要添加到Bundle中。
点击File-New-Project-macOS-Bundle,取名为SDKDemoBundle。
创建名为 SDKDemoBundle(最后要生成的 Bundle 文件名称)的工程,注意 Bundle 默认是 macOS 系统的,Xcode 高版本中需要在 macOS => Framework & Library 选项下找到。
2.修改 Bundle 配置信息
因为 Bundle 默认是 macOS 系统的,所有需要修改他的信息,修改成 iOS 系统。
TARGETS -SDKDemoBundle-BuildSettings-Base SDK 设置 iOS
需要把Build Active Architecture Only修改为NO,否则生成的库就只支持当前选择设备的架构。
设置 Build Setting 中的 COMBINE_HIDPI_IMAGES 为 NO,否则 Bundle 中的图片就是 tiff 格式了。
COMBINE_HIDPI_IMAGES设置为NO
3.可选配置
作为资源包,仅仅需要编译就好,无需安装相关的配置,设置 Skip Install 为 YES。
清除Installation Directory路径信息。
4.修改研发者证书,不修改报这个错误
把工程目录下的Build Settings下Base SDK修改为iOS,需要把Build Active Architecture Only修改为NO,否则生成的库就只支持当前选择设备的架构。作为资源包,仅仅需要编译就好,无需安装相关的配置,设置 Skip Install 为 YES
最关键是把工程目录下的Build Settings下Code Signing Identity的苹果研发者证书换称iOS研发者证书
5.添加文件
将资源文件或文件夹拖动到工程中的 SDKDemoBundle 文件夹下面。
6.编译生成 Bundle 文件
我们分别选择 Generic iOS Device 和任意一个模拟器各编译一次,编译完后,我们会看到工程中 Products 文件夹下的 SDKDemoBundle.bundle 由红色变成了黑色。
7.选中工程中 Products 文件夹下的 SDKDemoBundle.bundle右键点击显示包内容,查看生成的文件。我们看到它为真机和模拟器都生成了 .bundle 资源文件。
我们可以看到之前拖拽到工程中的资源文件都在其中。
Debug-iphoneos文件夹下的是真器使用的.bundle 资源文件,Debug-iphonesimulator文件夹下的是模拟器使用的.bundle 资源文件。
8.然后你把你需要的.bundle 资源文件拷贝到你需要的工程中就可以正常使用了。
注意:.bundle 资源文件分真机和模拟器两种资源,模拟器的资源真机可以使用。模拟器的资源多了一个_CodeSignature文件夹,下面有四个及以上文件每运行一种模拟器多一个CodeRequirements开头的文件。所以发布时还是用真机资源吧,不然多了一些文件。
9.若需要生成发布的动态库,需要修改环境设置Release,在Generic iOS Device下编译 (选择该target,command + B)生成发布版本的动态库。
10.使用.bundle 资源文件中的xib
- (instancetype)init { self = [super initWithNibName:@"SDKDemoViewController" bundle:[NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"SDKDemoBundle" withExtension:@"bundle"]]]; if (self) { return self; } return self; }
// 设置文件路径 NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"SDKDemoBundle" ofType:@"bundle"]; NSBundle *resourceBundle = [NSBundle bundleWithPath:bundlePath]; // 加载 nib 文件 UINib *nib = [UINib nibWithNibName:@"SDKDemoViewController" bundle:resourceBundle]; NSArray *viewObjs = [nib instantiateWithOwner:nil options:nil]; // 获取 xib 文件 UIView *view = viewObjs.lastObject; view.frame = CGRectMake(20, 50, self.view.bounds.size.width - 40, self.view.bounds.size.width - 40); [self.view addSubview:view];
11.使用.bundle 资源文件中图片
指定绝对路径的形式
UIImage *image = [UIImage imageNamed:@"SDKDemoBundle.bundle/unionpay@2x.png"]; 拼接路径的形式 NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"SDKDemoBundle" ofType:@"bundle"]; NSString *imgPath= [bundlePath stringByAppendingPathComponent:@"unionpay@2x.png"]; UIImage *image = [UIImage imageWithContentsOfFile:imgPath];
Bundle 和 xcassets
1、工程中所有使用 Asset Catalog 管理的图片(在 .xcassets 文件夹下),最终输出的时候,都会被压缩到 Assets.car 内。
2、反之,不在 Assets.car 内的,我们将它统一归类为 Bundle 管理的。
Bundle 和 xcassets 的主要区别
1)xcassets 里面的图片,只能通过 imageNamed 加载。Bundle 还可以通过 imageWithContentsOfFile 等方式。2)xcassets 里的 2x 和 3x。而 Bundle 会都包含。(App Slicing)3)xcassets 内,可以对图片进行 Slicing,即裁剪和拉伸。Bundle 不支持。4)Bundle 内支持多语言,xcassets 不支持。
为了证明Bundle 可以根据设备自动适配的,可以用下面的代码进行测试。当它找不到对应倍图时会自动找其它的倍图。那些说 Bundle不会根据设备进行自动适配倍图的人纯属臆想,没有进行现实测试。格式是奋斗在第一线的程序猿,我的文章都进行了现实测试的,为了以后少走湾路,希望能给自己和大家带来帮助。好记性不如烂笔头。
测试的是iPhone Xs Max模拟器,app的LaunchImage适配了iPhone Xs Max,为了测试,二倍图和三倍图不相同,尺寸也不相同。
UIImage *image = nil; UIImage *image1 = [UIImage imageNamed:@"ELockSDKBundle.bundle/common_icon_loading@3x.png"]; NSLog(@"common_icon_loading@3x.png image1.size.height:%.f", image1.size.height); UIImage *image2 = [UIImage imageNamed:@"ELockSDKBundle.bundle/common_icon_loading@2x.png"]; NSLog(@"common_icon_loading@2x.png image2.size.height:%.f", image2.size.height); UIImage *image3 = [UIImage imageNamed:@"ELockSDKBundle.bundle/common_icon_loading.png"]; NSLog(@"common_icon_loading.png image3.size.height:%.f", image3.size.height); if([UIScreen mainScreen].scale >= 3) { image = [UIImage imageNamed:@"ELockSDKBundle.bundle/common_icon_loading@3x.png"];//[UIImage imageNamed:@"common_icon_loading"]; } else { image = [UIImage imageNamed:@"ELockSDKBundle.bundle/common_icon_loading@2x.png"];//[UIImage imageNamed:@"common_icon_loading"]; } NSLog(@"common_icon_loading.png image.size.height:%.f", image.size.height);
测试效果:使用image = [UIImage imageNamed:@"ELockSDKBundle.bundle/common_icon_loading@3x.png"];和image = [UIImage imageNamed:@"ELockSDKBundle.bundle/common_icon_loading.png"];加载的是同一张图。所以Bundle会根据设备自动适配倍图的。下面是打印的日志:
2019-03-13 10:44:09.815380+0800 BLockSDKUnitTest[6647:199720] common_icon_loading@3x.png image1.size.height:44 2019-03-13 10:44:09.885936+0800 BLockSDKUnitTest[6647:199720] common_icon_loading@2x.png image2.size.height:24 2019-03-13 10:44:09.956959+0800 BLockSDKUnitTest[6647:199720] common_icon_loading.png image3.size.height:44 2019-03-13 10:44:09.957200+0800 BLockSDKUnitTest[6647:199720] common_icon_loading.png image.size.height:44