封装三方库时如何正确读取Bundle资源文件

先说我常用的解决方法

```

NSBundle *bundle = [NSBundle bundleForClass:[self class]];       

NSURL *url = [bundle URLForResource:@"Test" withExtension:@"bundle"];       

NSBundle *imageBundle = [NSBundle bundleWithURL:url];               

NSString *path = [imageBundle pathForResource:@"TEST" ofType:@"db"];

```

在进行组件化或者打静态库的时候,不可避免的会出现资源文件的处理,一般会有如下几种情况

pod库中的代码读取自身pod库中的资源

pod库中代码读取其他pod库资源

主工程读取pod库资源

pod库读取主工程资源(这个读取思想是错误的)

通常如果我们在主工程调用主工程的资源时,可以直接imageName或者[mainbundle pathForResource]读取,但是在用pod进行管理的时候,pod中的资源文件也会变成bundle加入到mainBundle中,但是由于最直接的bundle并不是mainBundle,所以这种方法是行不通的,关键是要取到资源相关联的bundle

oc工程的podfile一般是不使用use_frameworks!的,swift和自己创建的lib库是默认有的,关于这两点的差异,如果不使用framework,pod里的资源文件会被打成bundle放在mainbundle下面,由于开发中每个pod库对于use_frameworks!的使用情况不一样,我们在设计工具类的时候要两者兼容 ,podspec如下

podspec

接下来我们依次看两种情况下bundle的差异

不使用framework的mainBundle.png

对于之中种不使用framewok的情况资源调用很简单,只需要一个bundlename参数

NSURL*associateBundleURL=[[NSBundle mainBundle]URLForResource:bundleName withExtension:@"bundle"];NSBundle*bundle=[NSBundle bundleWithURL:associateBundleURL];

使用framework的mainBundle

对于使用framework的情况下的,bundle就会被分配在每个pod.framework下,这时候mainbundle的子目录就变成这样了,这个目前我还没找到好的方法(说[self class]的等下我说明下),所以目前我就是拼接的方式获取bundle路径,这里需要两个参数bundlename和podname

NSURL*associateBundleURL=[[NSBundle mainBundle]URLForResource:@"Frameworks"withExtension:nil];associateBundleURL=[associateBundleURL URLByAppendingPathComponent:podName];associateBundleURL=[associateBundleURL URLByAppendingPathExtension:@"framework"];NSBundle*associateBunle=[NSBundle bundleWithURL:associateBundleURL];associateBundleURL=[associateBunle URLForResource:bundleName withExtension:@"bundle"];NSBundle*bundle=[NSBundle bundleWithURL:associateBundleURL];

这就是两个模式下bundle资源的读取,两种条件下合并之后就变成这样:

@implementationNSBundle(AssociatedBundle)/**

获取文件所在name,默认情况下podName和bundlename相同,传一个即可

@param bundleName bundle名字,就是在resource_bundles里面的名字

@param podName pod的名字

@return bundle

*/+(NSBundle*)bundleWithBundleName:(NSString*)bundleName podName:(NSString*)podName{if(bundleName==nil&&podName==nil){@throw@"bundleName和podName不能同时为空";}elseif(bundleName==nil){bundleName=podName;}elseif(podName==nil){podName=bundleName;}if([bundleName containsString:@".bundle"]){bundleName=[bundleName componentsSeparatedByString:@".bundle"].firstObject;}//没使用framwork的情况下NSURL*associateBundleURL=[[NSBundle mainBundle]URLForResource:bundleName withExtension:@"bundle"];//使用framework形式if(!associateBundleURL){associateBundleURL=[[NSBundle mainBundle]URLForResource:@"Frameworks"withExtension:nil];associateBundleURL=[associateBundleURL URLByAppendingPathComponent:podName];associateBundleURL=[associateBundleURL URLByAppendingPathExtension:@"framework"];NSBundle*associateBunle=[NSBundle bundleWithURL:associateBundleURL];associateBundleURL=[associateBunle URLForResource:bundleName withExtension:@"bundle"];}NSAssert(associateBundleURL,@"取不到关联bundle");//生产环境直接返回空returnassociateBundleURL?[NSBundle bundleWithURL:associateBundleURL]:nil;}@end

以上就是读取pod中bundle的方式,bundle拿到之后,资源文件就可以各种方式拿了。

关于其他文章说的【self class】取bundle的理解

先贴出其他文章的代码

NSBundle*bundle=[NSBundle bundleForClass:[MYSomeClass class]];NSURL*bundleURL=[bundle URLForResource:bundleNamewithExtension:@"bundle"];NSBundle*resourceBundle=[NSBundle bundleWithURL:bundleURL];

接下来说说我对这里,个人觉得像这种取bundle资源的方法是应该放在一个公用的方法库里(pod库),而且用分类的方式实现会更好理解一点,这里关于【self class】就涉及到两个问题,

在分类里面【self class】取bundle是取不到的

公共资源会单独形成一个pod,这时候如果其他pod调用这个资源pod,就没有class这一说

由于这两个问题,所以我目前采用的是上面那种自己拼接url的方案

链接:https://www.jianshu.com/p/4188b6447d56

你可能感兴趣的:(封装三方库时如何正确读取Bundle资源文件)