美文网首页iosiOS开发技术分享GXiOS
Pod资源文件的正确Bundle读取

Pod资源文件的正确Bundle读取

作者: moxacist | 来源:发表于2018-01-30 21:24 被阅读2045次

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

  • 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资源的读取,两种条件下合并之后就变成这样:

@implementation NSBundle (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不能同时为空";
    }else if (bundleName == nil ) {
        bundleName = podName;
    }else if (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");
    //生产环境直接返回空
    return associateBundleURL?[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的方案

相关文章

网友评论

    本文标题:Pod资源文件的正确Bundle读取

    本文链接:https://www.haomeiwen.com/subject/glfhzxtx.html