问题实践
我们在开发Flutter iOS侧的插件时,有时会在插件类里面使用到图片等资源,如果直接在插件类里面直接使用 [UIImage imageName:@"*.png"] 的方式引入,图片不会显示;这里我们可以使用bundle的方式引入和使用图片,具体实践过程如下:
-
插件的文件结构
-
在 .podspec文件中添加以下配置
s.resource_bundles = {'Image_Picker'=>['Assets/*.png']}
然后在主工程根目录执行pod install(注意一定要执行,否则podspec不会生效),执行完pod install可以在主工程的Pods\Products目录下看到生成的Image_Picker.bundle,或者在主工程的Product\Runner.app 右键查看包内容看到Image_Picker.bundle;
- 在类文件中的引用方式
/**
根据图片名字从bundle获取UIImage对象
*/
- (UIImage *)resourceBundleOfImageName:(NSString *)imageName {
NSBundle *mainBundle = [NSBundle bundleForClass:[self class]];
NSBundle *resourceBundle = [NSBundle bundleWithPath:[mainBundle pathForResource:@"Image_Picker" ofType:@"bundle"]];
UIImage *image = [UIImage imageNamed:imageName inBundle:resourceBundle withConfiguration:nil];
return image;
}
这样就可以显示了!
知识点延伸
这里涉及到两个知识点:
- Asset Catalog Asset Catalog,是Xcode提供的一项图片资源管理方式。每个Asset表示一个图片资源,但是可以对应一个或者多个实际PNG图,比如可以提供@1x, @2x, @3x多张尺寸的图以适配;在macOS上,还可以通过指定日间和夜间不同Appearances的两套图片。
这种资源,在编译时会被压缩,然后在App运行时,可以通过API动态根据设备scale factor(Mac上日夜间设置)来选择对应的真实的图片渲染。
- App Thinning App Thinning,是苹果平台(iOS/tvOS/watchOS)上的一个用于优化App包下载资源大小的方案。在App包提交上传到App Store后,苹果后台服务器,会对不同的设备,根据设备的scale factor,重新把App包进行精简,这样不同设备从App Store下载需要的容量不同,3x设备不需要同时下载1x和2x的图。
但是,这套机制直接基于Asset Catalog,换言之,只有在Asset Catalog中引入的图片,才可以利用这套App Thinning。直接拷贝到App Bundle中的散落图片,所有设备还是都会全部下载。因此如何尽量提升Asset Catalog利用率,是一个很大的包大小优化点。
参考文献: dreampiggy.com/2018/11/26/…
文章详细讲解了s.resource_bundles 和 s.resource 引入方式的区别和优缺点,还有使用use_frameworks!和不使用use_frameworks!的区别。