iOS Asset Catalog and Bundle

对于png文件,使用Asset Catalog管理更有优势,这也是苹果在iOS 9后推荐的方式,它的好处显然易见,支持app slicing、支持设置拉伸区域、给不同的机型配置不同的图片、配置渲染颜色等。

背景

项目采用CocoaPods管理,大部分组件使用bundle管理图片文件,近期发现jenkins打包一直失败,排查发现在执行'[CP] Copy Pods Resources'脚本时,bundle中的所有图片文件路径会拼接作为xargs的参数,当文件数量达到一定值时,参数长度就超过限制。针对这个问题的改进方案是图片资源使用Asset Catalog(仅会有一个Assets.car文件)。

Asset Catalog

对于png文件,使用Asset Catalog管理更有优势,这也是苹果在iOS 9后推荐的方式,它的好处显然易见,支持app slicing、支持设置拉伸区域、给不同的机型配置不同的图片、配置渲染颜色等。在xcassets中的图片可以直接通过UIImage(named: _name)加载;其他data类型的数据文件,比如mp3等,如果也放在xcassets管理,则需要使用NSDataAsset加载,这样就有个问题,NSDataAsset可以便捷的获取数据内容,但无法提供路径。这和xcassets的原理有关:所有的文件最终会打包成car文件,car是一个压缩文件,网上有很多解压car的工具,比如acextract,并没有文件路径的概念,xcassets的图片也因此不能通过imageWithContentsOfFile的方式加载,这在一些场景下并不友好。另外imageNamed的带缓存的,也不适合加载特别大的图片。推荐的方式是:

  • png、gif图片采取xcassets管理;
  • mp3等数据文件采用bundle的方式管理;

多个xcassets文件

新建Xcode项目时,默认新建了Assets.xcassets文件,也可以新建其他名称的xcassets文件。为防止名称冲突,可以为同一个xcassets文件设置一个namespace,最终所有的xcassets文件会打包成Assets.car文件。

在podspec文件中引入xcassets

在以CocoaPods进行组件管理的项目中,每一个podspec文件都可以拥有独立的xcassets,典型的配置如下:

s.resource_bundles = {
    'easeapi' => ['Assets/*.{xcassets}']
}

在编译过程中,Assets目录下的所有xcassets文件会被压缩成Assets.car文件,并放置在easeapi.bundle中。此时,可通过以下方式访问图片或其他数据文件。

UIImage.init(named: "name", in: "bundle对象", compatibleWith: nil)
NSDataAsset.init(name: "name", bundle: "bundle对象")

CocoaPods使用Asset Catalog的一个问题

s.resource_bundles = {
    'easeapi' => ['Assets/*.{xcassets}']
}

podspec文件中使用resource_bundles,在CocoaPods 1.3.1版本中pod install后,发现对应的Support Files目录缺少.xcconfig文件,此时使用UIImage.init读取的image对象为nil。修复方式是不使用resource_bundles,而直接用bundle文件。使用pod package可以产出最终的bundle文件

pod package easeapi.podspec \
--force --no-mangle --embedded --exclude-deps \
--spec-sources=xxx \
--verbose

将resource_bundles修改为:

s.resource = 'easeapi.bundle'

其它文章

iOS Appium自动化测试框架原理简析
iOS DeviceCheck详解
iOS 13 Scene Delegate and multiple windows
iOS Sign With Apple实践