iOS组件化实现之:资源组件库
1 资源有哪些
笼统的可以说,只要不是代码文件的,都可以算是资源文件,举些例子,包括但不限于:图片、音频、视频、动画、字体、多语言文件(.strings)、各类资源包、内置数据库、二进制加密文件不等
2 为什么要做
存在一些可复用的资源,举些例子,包括但不限于:
-
通用样式图标
导航条图标、头像、按钮、单/复选框、通用背景图片等
-
通用媒体文件
通用的点击音效、提示音、过场动画、加载动画等
-
其他通用文件
城市列表、字体、第三方预置资源等
由于部分资源是有通用性,因此将这些通用资源提取出来,形成组件,可服务于更多项目,提升集成的效率,降低研发成本
3 怎么做
3.1 新建一个Pod私有库
3.2 迁移主工程资源
主工程:
中的资源一般散落在各处,即遍是不一定全部存放在asset集合中,可以通过Xcode Project Navigator底部的搜索栏,通过后缀名(.png / .jpg /.webp /.mp3 /,mp4 ……)检索出资源
资源组件库:
asset文件夹下存放主工程迁移的资源。
存放形式可以以下形式:
- xcassets集合
- 散落的资源文件
配置podspec:
通过指定resource_bundles进行资源的配置
1
2
3
4
5
6
7
s.resource_bundles = {
'PSCResource' => [
'PSCResource/Assets/PSCCommon.xcassets',
'PSCResource/Assets/PSCCommonResources/**/*',
'PSCResource/Assets/XXProj.xcassets',
'PSCResource/Assets/XXProjResources/**/*']
}
3.3 资源读取方式
资源组件化之前,使用一般是
//图片:imageNamed
[UIImage imageNamed:@"pic"];
//资源:通过mainBundle进行:
[[NSBundle mainBundle] pathForResource:@"name" ofType:@"ext"];
这是因为,主工程里的资源,一般是打包到xx.app的根目录(xcasset以asset.car存在)
组件库里的资源是打包 xx.framework/xx.bundle
1
2
3
……/Debug-iphoneos/xxx.app/Frameworks/xx.framework/xx.bundle/pic.png
……/Debug-iphoneos/xxx.app/Frameworks/xx.framework/xx.bundle/asset.car
……
直接通过下列方法获取为空
//组件库资源,通过以下方法获取为nil
[UIImage imageNamed:@"pic"];
[[NSBundle mainBundle] pathForResource:@"name" ofType:@"ext"];
组件库资源获取方法是为下列类添加类别
- UIImage:
@interface UIImage (PSCResource)
/// 从 PSCResource 通过图片名称获取UIImage
/// - Parameter name: 图片名称
+ (UIImage *)pscImageNamed:(NSString *)name;
@end
@implementation UIImage (PSCResource)
+ (UIImage *)pscImageNamed:(NSString *)name{
NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(kCurResPodName)];
NSURL *url = [bundle URLForResource:kCurResBunldeName withExtension:@"bundle"];
if (url) {
NSBundle *imageBundle = [NSBundle bundleWithURL:url];
UIImage *img = [UIImage imageNamed:name inBundle:imageBundle compatibleWithTraitCollection:nil];
if (img) {
return img;
}
}
//这里兜个底,兼容资源还在主工程的时候,使用mainBundle
return [UIImage imageNamed:name];
}
@end
- NSBunlde:
@interface NSBundle (PSCResource)
/// 私有库获取资源
/// - Parameters:
/// - name: 资源名
/// - ext: 资源类别
+ (NSString *)pscPathForResource:(NSString *)name ofType:(NSString *)ext;
@end
@implementation NSBundle (PSCResource)
+ (NSString *)pscPathForResource:(NSString *)name ofType:(NSString *)ext {
NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(kCurResPodName)];
NSURL *url = [bundle URLForResource:kCurResBunldeName withExtension:@"bundle"];
if (url) {
NSBundle *resBundle = [NSBundle bundleWithURL:url];
NSString *path = [resBundle pathForResource:name ofType:ext];
if (path) {
return path;
}
}
//这里兜个底,兼容资源还在主工程的时候,使用mainBundle
return [[NSBundle mainBundle] pathForResource:name ofType:ext];
}
@end
3.4 主工程读取替换
检索主工程里所有的方法:
1
2
[UIImage imageNamed:@"pic"];
[[NSBundle mainBundle] pathForResource:@"name" ofType:@"ext"];
替换成:
[UIImage pscImageNamed:@"xx"]
NSString *hotPath = [NSBundle pscPathForResource:@"yy" ofType:@"zz"];
最后检验下上述调用是否正常?