在组件化开发的过程中,在业务组件中,常常会加载各种资源文件,例如png图片,mp3音频。js文件,txt文件等等。我们此时用之前常用的方法[NSBundle mainBundle] pathForResource:@"123.png" type:nil]
时发现获取不到路径了。具体原因我们下面进行详细的分解说明。
什么是NSBundle?
bundle 是一个目录,其中包含了程序会使用到的资源.这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in).对应bundle,cocoa为我们提供了类NSBundle
。bundle 文件的创建,只需要在本地创建一个文件夹,给文件夹添加后缀.bundle
就行了。在没有进行组件化开发的时候我们接触更多的是mainBundle
。[NSBundle mainBundle]
是获得NSBundle
的一个单例对象,而[[NSBundle mainBundle] resourcePath]
就是你的app打包后的路径。为了获取app目录下的文件,我们常用的几个方法是:
- (nullable NSURL *)URLForResource:(nullable NSString *)name withExtension:(nullable NSString *)ext
+ (nullable NSString *)pathForResource:(nullable NSString *)name ofType:(nullable NSString *)ext inDirectory:(NSString *)bundlePath
为什么组件化后[UIImage imageName:@"123.png"]
不起作用了
在我们日常开发的过程中, 绘制UI用到比较多的就是[UIImage imageName:@"123.png"]
,是什么原因呢,主要原因是[UIImage imageName:@"123.png"]
是在mainbundle下去寻找资源文件的,而组件化后,相关的图片是在自己的pod组件对应的bundle下, 再使用之前的方法已经无法找到相关的图片。为了解决这个问题我写了两个方法来满足这个需求。但是为了方便大家的理解,我这里先和大家说说使用cocoapod创建组件,资源文件的保存方式。
组件化时资源文件如何配置
在组件化开发的过程中,比较常见的podspec文件对资源文件的配置
有几种形式。
1):资源文件在组件中相互独立
s.resource_bundles
优点:
组件独立
有资源文件版本管理
资源文件修改等跟着业务组件正常发版
注:这一中也是比较常见的,常见的开源库的资源文件都是这样保存的。
针对这一种情况,我这边写了相关的方法可以获取
/**
获取某个Bundle下的文件的路径
@param fileName 文件的名字,可以带后缀名
@param podName pod组件的名字
@param ext 文件的后缀名
@return 文件的路径
*/
+ (nullable NSString *)pathWithFileName:(nonnull NSString *)fileName podName:(nonnull NSString *)podName ofType:(nullable NSString *)ext;
/**
获取某个podName对象的bundle对象
@param podName pod的名字
@return 对应的bundle对象
*/
+ (nullable NSBundle *)bundleWithPodName:(nonnull NSString *)podName;
/**
获取某个podName下的nib文件并创建对象
@param nibName xib文件的名字
@param podName pod库名
@return 创建好的对象
*/
+ (nullable id)loadNibName:(nonnull NSString *)nibName podName:(nonnull NSString *)podName;
/**
获取某个pod下的UIStoryboard文件的对象
@param name UIStoryboard 的名字
@param podName pod库名
@return UIStoryboard 对象
*/
+ (nullable UIStoryboard *)storyboardWithName:(nonnull NSString *)name podName:(nonnull NSString *)podName;
/**
在模块内查找UIImage的方法
@param imageName 图片的名字,如果是非png格式的话,要带上后缀名
@param podName pod库名
@return UIImage对象
*/
+ (nullable UIImage *)imageWithName:(nonnull NSString *)imageName podName:(nonnull NSString *)podName;
具体实现如下:
+ (nullable NSString *)pathWithFileName:(nonnull NSString *)fileName podName:(nonnull NSString *)podName ofType:(nullable NSString *)ext{
if (!fileName ) {
return nil;
}
NSBundle * pod_bundle =[self bundleWithPodName:podName];
if (!pod_bundle.loaded) {
[pod_bundle load];
}
NSString *filePath =[pod_bundle pathForResource:fileName ofType:ext];
return filePath;
}
+ (nullable NSBundle *)bundleWithPodName:(nonnull NSString *)podName{
if (!podName) {
return nil;
}
NSBundle * bundle = [NSBundle bundleForClass:NSClassFromString(podName)];
NSURL * url = [bundle URLForResource:podName withExtension:@"bundle"];
NSArray *frameWorks = [NSBundle allFrameworks];
if (!url) {
for (NSBundle *tempBundle in frameWorks) {
url = [tempBundle URLForResource:podName withExtension:@"bundle"];
if (url) {
break;
}
}
}
NSBundle * pod_bundle =[NSBundle bundleWithURL:url];
if (!pod_bundle.loaded) {
[pod_bundle load];
}
return pod_bundle;
}
+ (nullable id)loadNibName:(nonnull NSString *)nibName podName:(nonnull NSString *)podName{
NSBundle *bundle =[self bundleWithPodName:podName];
id object = [[bundle loadNibNamed:nibName owner:nil options:nil] lastObject];
return object;
}
+ (nullable UIStoryboard *)storyboardWithName:(nonnull NSString *)name podName:(nonnull NSString *)podName{
NSBundle *bundle =[self bundleWithPodName:podName];
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:name bundle:bundle];
return storyBoard;
}
+ (nullable UIImage *)imageWithName:(nonnull NSString *)imageName podName:(nonnull NSString *)podName {
NSBundle * pod_bundle =[self bundleWithPodName:podName];
if (!pod_bundle.loaded) {
[pod_bundle load];
}
UIImage *image = [UIImage imageNamed:imageName inBundle:pod_bundle compatibleWithTraitCollection:nil];
return image;
}
demo地址如下 demo下载地址
注:当然了, pod创建组件库还有一些其他的资源文件管理的方案,但存在一些问题,不是官方推荐的,这里我就不过多介绍了,以免误导大家。
更多优质文章,可以微信扫码关注: