Leon’s Blog

Dreams don't work unless you do.

制作.bundle文件

在我们使用第三方框架时经常会看到xxx.bundle的文件,我们找到该文件,右键显示包内容,会看到很多图片,配置文件,.xib等资源文件。在我们SDK打包的过程中,也会将资源文件一并打包成.bundle文件使用,那是为什么呢?其实.bundle文件与我们平时的文件夹并无太大区别,在我看来只是加了后缀罢了,它更像是一个包,如果在工程外部想查看内部的文件需要显示包内容查看,在移动包文件的过程中在一定程度上也降低了他人对包内容误改的几率。

什么是bundle文件?

简单理解,就是资源文件包。我们将许多图片、XIB、文本文件组织在一起,打包成一个Bundle文件。方便在其他项目中引用包内的资源。

Bundle文件的特点?

Bundle是静态的,也就是说,我们包含到包中的资源文件作为一个资源包是不参加项目编译的。也就意味着,bundle包中不能包含可执行的文件。它仅仅是作为资源,被解析成为特定的2进制数据。

如何制作.bundle文件?

方式1:

  1. 创建一个文件夹
  2. 将资源文件放到创建的文件夹中
  3. 给文件夹添加.bundle后缀
  4. 把.bundle文件拖拽到项目中使用即可
这里需要注意的是:如果资源中包含.xib文件,需要使用命令把xib转化为nib文件:
1
$ ibtool --errors --warnings --output-format human-readable-text --compile 文件名.nib 文件名.xib
如果不转换, 读取的时候会导致如下错误:
1
2
3
4
Terminating app due to uncaught exception 
'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle:
'NSBundle </var/mobile/Applications/C6718DB8-0C0F-4D38-84E6-55C145279957
/Documents/asset-4.bundle> (not yet loaded)' with name 'file''

方式2:

1.新建bundle项目

2.添加资源文件

3.因为只有macOS可以创建bundle项目,所以我们需要将build setting中
的Base SDK值改成iOS的版本

4.编译工程生成.bundle文件

使用bundle中的资源

由于bundle是静态的,不会进行编译的资源文件,所以要使用bundle中的资源,首先要找到我们生成Bundle文件路径来生成NSBundle实例,然后再使用资源名字从生成的NSBundle实例中找到对应的资源。

获取Bundle中的nib资源文件

1
2
3
4
5
6
// 在SecondVC的初始化方法中加载
- (instancetype)init {
NSBundle *bundle = [[NSBundle alloc]initWithPath:[[NSBundle mainBundle] pathForResource:@"CreateBundle" ofType:@"bundle"]];
self = [super initWithNibName:@"SecondVC" bundle:bundle];
return self;
}

或者在需要使用的地方直接使用initWithNibName:bundle:去加载

1
2
3
NSBundle *bundle = [[NSBundle alloc]initWithPath:[[NSBundle mainBundle] pathForResource:@"CreateBundle" ofType:@"bundle"]];
SecondVC *second = [[SecondVC alloc]initWithNibName:@"SecondVC" bundle:bundle];
[self presentViewController:second animated:YES completion:nil];

获取Bundle中的图片资源

方法1:

1
2
UIImage *image = [UIImage imageNamed:@"CreateBundle/image1"];
UIImageView *imageView = [[UIImageView alloc]initWithImage:image];

方法2:

1
2
3
4
5
6
7
// 获取Bundle路径
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"CreateBundle" ofType:@"bundle"];
// 拼接图片资源路径
NSString *imgPath= [bundlePath stringByAppendingPathComponent :@"image1.jpeg"];
// 路径加载
UIImage *image=[UIImage imageWithContentsOfFile:imgPath];
UIImageView *imageView = [[UIImageView alloc]initWithImage:image];

经验分享

如果是bundle文件外部的xib或者StoryBoard要使用图片资源的话,在设置图片的位置要使用 bundle名/资源名 这种样式去加载,与纯代码获取图片资源的方式1一样。如果是bundle文件内部的xib或者storyBoard的话,直接资源名字就可以了。