先说我常用的解决方法
```
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