Pod库图片资源管理

2019-11-12  本文已影响0人  tom555cat

CocoaPods中管理图片资源

CocoaPods在.podspec文件中描述资源的字段有两个,resources和resouce_bundles。

resources

使用方式如下:

spec.resource = 'Resources/HockeySDK.bundle'
spec.resources = ['Images/*.png', 'Sounds/*']

CocoaPods不推荐使用resources,因为它会产生图片资源冲突。

使用"*.png"描述资源

此时打包之后Pod库图片会出现在安装包里,没有进入主工程的Assets.car中,不同Pod库中相同名字的图片会在安装包里冲突导致被覆盖掉。

使用"*.bundle"描述资源

此时打包之后Pod库的bundle文件会出现在安装包里,不同Pod库的同名bundle文件会融合成一个bundle文件,而bundle文件中相同名字的图片就会冲突然后被覆盖掉。

使用"*.xcassets"描述资源

此时Pod库的.xcassets中的图片会被打包到主工程的Assets.car中,不同Pod库中相同名字的图片会在Assets.car中出现冲突然后被覆盖。

上面详细描述了使用“resources”来描述图片资源时,打包之后图片所在的位置,及造成图片冲突的原因。

resource_bundles

使用方式如下:

spec.ios.resource_bundle = { 'MapBox' => 'MapView/Map/Resources/*.png' }
spec.resource_bundles = {
    'MapBox' => ['MapView/Map/Resources/*.png'],
    'MapBoxOtherResources' => ['MapView/Map/OtherResources/*.png']
}

resource_bundles内部通过一对key-value来描述资源,对每一个key生成一个bundle,value则是该bundle下的图片资源;为了减少key冲突,CocoaPods建议key至少包含Pod的名字,同一个Pod库下不同的bundle在Pod的名字之后加上不同的后缀。

CocoaPods推荐使用resource_bundles来管理图片资源,但是有一个非常严重的问题需要注意:https://github.com/CocoaPods/CocoaPods/issues/8431,就是当项目中有一个Pod库采用了resources&xcasset的方式描述资源时,项目所有Pod库中的xcasset都会被拷贝到主工程的Assets.car中;此时如果有一个Pod库使用了resource_bundles&xcasset描述资源时,该Pod的xcasset中的图片也会被拷贝到主工程的Assets.car中,这会与Pod库的自己bundle中生成的Assets.car图片造成重复,产生这个问题的地方在于执行pod install之后生成的Pods-xxxxx-resource.sh脚本里的如下代码中:

if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ]
then
  # Find all other xcassets (this unfortunately includes those of path pods and other targets).
  OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
  while read line; do
    if [[ $line != "${PODS_ROOT}*" ]]; then
      XCASSET_FILES+=("$line")
    fi
  done <<<"$OTHER_XCASSETS"

  if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then
    printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
  else
    printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist"
  fi
fi

上述issue中提供了可以复现的demo,而且CocoaPods的作者按时安排在1.9版本中解决这个问题。

CocoaPods中图片资源的使用

NSBundle

再来熟悉一下文档中对Bundle的描述,"Apple uses bundles to represent apps, frameworks, plug-ins, and many other specific types of content",也就是说项目打包好的.app和frameworks都是一个Bundle。

查找并且打开一个NSBundle的创建方式大致分如下两种:

// Get the app's main bundle
NSBundle *main = [NSBundle mainBundle];
// Get the bundle containing the specified private class.
NSBundle *myBundle = [NSBundle bundleForClass:[MyPrivateClass class]];

获取当前Pod的图片资源

按照CocoaPods的建议,使用resource_bundles来描述资源文件,为了避免其他Pod库使用resources&xcasset给我们的Pod库造成麻烦,我们的Pod内部使用*.png来管理图片资源。

s.resource_bundles = {
  'XCCategory' => ['XCCategory/Assets/*.png']
}

我们目前Pod库是静态库,所以会在.app下生成一个"XCCategory.bundle"。

当前Pod可能作为动态库或者静态库,为了兼容这两种情况,使用bundleForClass:来获取Pod的bundle,当Pod作为静态库时,该方法返回的是mainBundle,当Pod作为动态库时,该方法返回的就是动态库本身。

下面代码获取到了XCCategory.bundle,然后从XCCategory.bundle中取出对应的图片。

+ (nullable UIImage *)xccategory_imageName:(NSString *)name {
    static NSBundle *resourceBundle = nil;
    if (resourceBundle == nil) {
        resourceBundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[XCCategoryViewController class]] pathForResource:@"XCCategory" ofType:@"bundle"]];
    }
    
    UIImage *image = [UIImage imageNamed:name inBundle:resourceBundle compatibleWithTraitCollection:nil];
    return image;
}
上一篇 下一篇

猜你喜欢

热点阅读