Resource code generator for iOS inspired by the Android
R resource class.
R resource class is generated by a tool called
aapt (Android Asset Packaging Tool) and makes it possible to access resources
conveniently and safely.
For example access images like this
or strings this
rgen makes it possible to access resources in a similar way on iOS by
reading the Xcode project file and generate code for resources that
will be available in the application bundle.
Load images like this
imageView.image = I.images.cuteSeal;
instead of this
imageView.image = [UIImage imageNamed:@"images/cute-seal.png"];
Specify resource paths like this
instead of this
[NSDictionary dictionaryWithContentsOfFile: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"files/dogs.plist"]];
Name localization string keys like this
instead of this
This is very nice for several reasons
- Less error-prone as you get compile time errors for missing images, files and string keys.
- Code completion for resources
- Less and nicer looking code
$ brew install --HEAD https://raw.github.com/wader/rgen/master/homebrew/rgen.rb
Compile from source:
$ git clone git://github.com/wader/rgen.git $ cd rgen $ xcodebuild $ cp build/Release/rgen /to/somewhere
Note that if you compile with Xcode 4 from the IDE the binary will probably not end up in the build directory. Instead try "Show in finder" on the rgen binary under "Products".
If don't want to compile yourself there is a binary for download compiled for Mac OS X 10.6 i386 that will work on both 32 and 64 bit systems.
Usage: ./rgen [-IPSv] xcodeproject [Output path] [Target name] -I, --images Generate I images property tree -P, --paths Generate P paths property tree -S, --stringkeys Generate S localizable string keys class --loadimages Generate loadImages/releaseImages methods --ipad Support @ipad image name scale suffix --ipad2x Support @2x as 1.0 scale image on iPad -v, --verbose Verbose output
Output path is specified code will be generated to
Resources.h in the current dirctory.
Target name is specified
rgen will merge
resources for all targets.
-S enables code generation for
the different resources. At least one must be enabled.
--imageimages generates two methods
releaseImages for each image directory.
can be used to load and retin all images in a dirctory and below.
releaseImages does the opposite by releasing them.
--ipad generates image loading code that will extend the normal
@2x suffix to also load
@ipad images if found on
--ipad2x generates image loading code that loads
images as scale 1.0 images on iPad devices. If
--ipad is enabled
@ipad image has priority.
-v enables verbose logging to see what rgen does.
Xcode build run script
Add a "New run script build phase" to your target. The run script should look
something like the one below.
which is used to make sure a user can
rgen is installed.
$SRCROOT will be assigned
RGEN="/path/to/rgen" which -s "$RGEN" && "$RGEN" -IPS "$PROJECT_FILE_PATH" "$SRCROOT/Classes/Resources"
Now build the target and two new files, in this case
Classes/Resources.h will be
created. Add these as source files to your project and then import
Resources.h where you want access to the resouces classes.
Then and your good to go!
To make thing even smoother you can add a
#import "Resources.h" line
rgen makes sure not to touch
the generated files if nothing has changed since last run to not trigger
Multi target setup
Every target should generate their own resource code and header file to make sure you get compile errors if you accidently use resources not available to a target.
Each target should have a build script, for example:
RGEN="/Users/mattias/src/rgen/build/Release/rgen" which -s "$RGEN" && "$RGEN" -IPS "$PROJECT_FILE_PATH" "$SRCROOT/Classes/TargetA" "$TARGET_NAME"
RGEN="/Users/mattias/src/rgen/build/Release/rgen" which -s "$RGEN" && "$RGEN" -IPS "$PROJECT_FILE_PATH" "$SRCROOT/Classes/TargetB" "$TARGET_NAME"
Now the files
TargetB.h will be
generated. Build each target and then add the files to the corresponding
target of your project.
Unfortunately the C preprocessor does not support comparing strings
#if TARGET_NAME == "TargetA" etc) so if you not already have some define
to distinguish between your targets you should add a define under
"Preprocessor marcos" in your build settings. A solution is to define TARGETA
to some dummy value for target TargetA and TARGETB for target TargetB.
Now add imports to some shared header file (
*_Prefix.pch is a good place).
#if defined(TARGETA) #import "TargetA.h" #elif defined(TARGETB) #import "TargetB.h" #endif
Run from terminal
Should work fine as long as your project does not have unsupported source trees paths. rgen uses various exported environment variables when running in a build script to figure out paths but can fallback to guessing paths based on project path.
rgen -IPS path/to/app.xcodeproj path/to/Classes/ResourcesTargetA TargetA
Will generate files
path/to/Classes/ResourcesTargetA.h with images, paths and string
keys found for target
Known issues and TODOs
- Support custome source tree paths
- Support Mac OS X applications. Autodetect via SDK (iphoneos/macosx) and generate NSImage code etc
- Read other .strings files (more then just Localizable.strings)
- Detect class name collisions
- Support document paths somehow. Specify list of known paths etc
- Rebuild dependencies seams to be calculated before starting build so you might need to build twice to use updated resources files
- Xcode plugin?
- RGEN path as user setting for shared project files. Make sure rgen is in path or use .xcconfig files?