在Android中,R.java文件管理资源,引用的方式R.xx.xx,非常方便。swift也借鉴R的方式,出了个库R.swift,用起来也是简单明了,不用先找到image的名字,像下面这样写就好,并且会有自动提示。
let icon = R.image.settingsIcon()
let font = R.font.sanFrancisco(size: 42)
let viewController = CustomViewController(nib: R.nib.customView)
let string = R.string.localizable.welcomeWithName("Arthur Dent")
原理说起来也挺简单,用脚本扫出在project文件中引用的资源(不过R.swift脚本是个可执行文件并没有开源),然后生成R.generated.swift,文件中是各种资源的struct。简化代码如下:
struct R {
struct image {
static let favorIcon = Rswift.ImageResource(bundle:R.hostingBundle, name: "eerste")
static func favorIcon(compatibleWith traitCollection: UIKit.UITraitCollection? = nil) -> UIKit.UIImage? {
return UIKit.UIImage(resource: R.image.favorIcon, compatibleWith: traitCollection)
}
}
那么,以类似的思路,在oc中也可以实现一套。
思路
这里先只讨论png图片的引用。
1.首先得有R文件,然后R类中得有image属性。
2.读取project文件,找到所引用的图片资源
3.遍历资源,如果是png类型,就生成相应的代码(包括接口和实现)插入到RImage类中。
R文件
新建R class。添加image属性,类型为RImage。
@interface R : NSObject
@property (noatomic) RImage *image;
@end
@interface RImage : NSObject
@end
读取project文件
project文件是ruby语法,cocoapods出过一个工具xcodeproj,可以来读取修改project。
随便打开一个project文件,会发现资源在ResourcesBuildPhase节点中。
写ruby脚本读取project文件:
require 'xcodeproj'
// project文件的路径
project_path = 'xxx'
project = Xcodeproj::Project.open(project_path)
project.targets.each do |target|
puts target.name
end
# 默认找第一个target
target = project.targets.first
# resources_build_phase
files = target.source_build_phase.files.to_a.map do |pbx_build_file|
pbx_build_file.file_ref.real_path.to_s
end.select do |path|
# 遍历路径,找到以png结尾的文件存起来
# xxx
end
插入代码
要能用R.image.imageName返回到相应的图片,RImage中必须要添加相应的imageName方法。
//RImage.h
- (UIImage *)favorIcon;
//RImage.m
- (UIImage *)favorIcon {
return [UIImage imageNamed:@"favorIcon" inBundle:[NSBundle mainBundle] compatibleWithTraitCollection:nil];
}
用ruby生成以上模板代码,然后打开RImage.h/RImage.m写入即可。
至此,最简单的R.image就完成了。string/xib/storyboard的生成也类似。然后写个shell脚本调用前面的ruby文件,在build phase中添加run script。
当然,实际中比这会复杂很多。
1、比如图片一般都是放到xcassets,这样就需要再遍历xcassets里面的图片。
2、资源有时不会全放mainbundle中,会有自建的bundle,那么读取图片时需要指定bundle。这就需要对bundle信息有记录。
3、jpg图片。