iOS12.4~12.5版本中CocoaPod库内UIImage(named:)返回nil问题
CocoaPod库图片资源在iOS12及以下版本读取失败问题解决方案
根因分析
- 该问题是iOS低版本系统兼容性+ CocoaPod资源打包逻辑共同导致的:
- iOS14+系统支持直接从自定义resource bundle中读取xcassets编译后的Assets.car资源,iOS12及更早版本的
UIImage(named:in:compatibleWith:)方法默认只会扫描主包、当前加载动态框架根目录下的Assets.car,无法识别嵌套在resource bundle内部的Assets.car文件 - 源码直接导入项目时,库内资源会被合并编译到主项目的Assets.car中,因此iOS12也能正常读取;通过pod导入时,若podspec使用
resource_bundles配置资源,CocoaPod会将库资源单独打包为独立的bundle文件存放在框架目录下,触发iOS12的兼容问题 - 你尝试的两种bundle获取逻辑没有问题,故障点出在图片读取的系统方法兼容性
- iOS14+系统支持直接从自定义resource bundle中读取xcassets编译后的Assets.car资源,iOS12及更早版本的
解决方案
方案1:修改podspec资源配置(最快适配)
将podspec中的resource_bundles配置替换为resources,CocoaPod会将库资源直接合并到主项目的Assets.car,和源码导入效果完全一致,无需修改业务代码即可兼容iOS12。
注意:如果库内资源存在和主项目重名的可能,该方案会出现资源覆盖问题,不建议使用。
方案2:修改图片读取逻辑(推荐,无重名风险)
保留resource_bundles配置避免资源重名,针对iOS12及以下版本单独做兼容处理:
- 先将图片从xcassets中移出,作为独立资源文件加入库的资源目录
- 使用如下代码读取图片:
// 获取资源bundle guard let bundle = Bundle(identifier: "com.mylib.mylib") else { return nil } // 高版本直接用系统方法 if #available(iOS 13.0, *) { return UIImage(named: "image_name", in: bundle, compatibleWith: nil) } // 低版本手动读取资源文件 else { guard let imagePath = bundle.path(forResource: "image_name", ofType: "png") else { return nil } return UIImage(contentsOfFile: imagePath) }
方案3:CoreImage读取Assets.car(仅小批量图片使用)
如果不想将图片移出xcassets,可以用CoreImage接口手动读取bundle内的Assets.car,性能略低于系统原生方法,适合少量图片读取场景:
guard let bundle = Bundle(identifier: "com.mylib.mylib") else { return nil } if #available(iOS 13.0, *) { return UIImage(named: "image_name", in: bundle, compatibleWith: nil) } else { guard let assetsCarPath = bundle.path(forResource: "Assets", ofType: "car") else { return nil } let ciImage = CIImage(contentsOf: URL(fileURLWithPath: assetsCarPath)) return UIImage(ciImage: ciImage) }
内容的提问来源于stack exchange,提问作者oto
相关产品推荐
相关产品推荐

