Skip to content

Instantly share code, notes, and snippets.

@KingOfBrian
Last active August 29, 2015 14:22
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KingOfBrian/d0e91c3f63c94398f349 to your computer and use it in GitHub Desktop.
Save KingOfBrian/d0e91c3f63c94398f349 to your computer and use it in GitHub Desktop.
Code Generation of .xcasset resources
import Foundation
/**
* Build script to generate a type safe wrapper around your projects .xcasset file.
* This will fail your build if you reference an image in your .xcasset file that has
* changed or been removed, as well as provide code completion help for all your images.
*
* Copy this file into a new `Run Phase` in your project, with `/usr/bin/env xcrun swift`
* specified for `Shell`.
*
* Configure the variables below:
*
* - outputPath: The location to write the generated file. This file must be manually
* added to your .xcodeproj.
* - path: The location to look for .imageset files (Which reside inside the .xcasset directory)
* - objcCompatible: A flag to use static methods or an enum.
*/
private struct Parameters {
static let outputFile = "./Assets.swift"
static let inputPath = "."
static let objcCompatible = false
static let separationCharacters = NSCharacterSet(charactersInString: "-_ ")
static let indentWidth = 4
}
// Transform image names in the xcasset to Tokens for use in code
func stringToCamelCase(input:String) -> String {
let parts = input.componentsSeparatedByCharactersInSet(Parameters.separationCharacters)
return parts.reduce("") { methodName, part in
methodName + (methodName == "" ? part : part.capitalizedString)
}
}
func stringToUpperCase(input:String) -> String {
let parts = input.componentsSeparatedByCharactersInSet(Parameters.separationCharacters)
return parts.reduce("") { methodName, part in
methodName + part.capitalizedString
}
}
// Formatting helper
func indent(lines:[String], level:Int = 1) -> [String] {
let space = "".join((0..<Parameters.indentWidth * level).map { (x:Int) in return " "})
return lines.map { "\(space)\($0)" }
}
// Functions to transform image names to lines of code
func imageNameToSwiftStaticFunc(imageName:String) -> String {
let methodName = stringToCamelCase(imageName)
return "static func \(methodName)() -> UIImage { return UIImage(named: \"\(imageName)\")! }"
}
func imageNameToSwiftEnum(imageName:String) -> String {
let methodName = stringToUpperCase(imageName)
return "case \(methodName) = \"\(imageName)\""
}
// Higher level transforms from image names to compilable code
let generated = ["/*",
" * WARNING: This file is automatically generated based on the contents",
" * of your .xcasset files. Do not modify.",
" */"]
func swiftImageExtension(imageNames:[String]) -> String {
let functions = indent(imageNames.map(imageNameToSwiftStaticFunc))
var lines = ["import UIKit", "extension UIImage {", "}"]
lines.splice(functions, atIndex: 2)
lines.splice(generated, atIndex: 0)
return "\n".join(lines)
}
func swiftImageEnum(imageNames:[String]) -> String {
let functions = indent(imageNames.map(imageNameToSwiftEnum), level:2)
var lines = ["import UIKit",
"extension UIImage {",
" enum AssetName : String {",
" }",
" convenience init!(asset:AssetName) {",
" self.init(named:asset.rawValue)",
" }",
"}"]
lines.splice(functions, atIndex: 3)
lines.splice(generated, atIndex: 0)
return "\n".join(lines)
}
// Obtain image names and pass them to a higher level transform function
if let paths = NSFileManager.defaultManager().subpathsAtPath(Parameters.inputPath) {
let imageNames = paths.filter {
$0.pathExtension == "imageset"
}.map { (x:String) -> String in
x.lastPathComponent.stringByDeletingPathExtension
}
let body = Parameters.objcCompatible ? swiftImageExtension(imageNames) : swiftImageEnum(imageNames)
try! body.writeToFile(Parameters.outputFile, atomically:true, encoding: NSUTF8StringEncoding)
}
else {
print(" warning: Unable to find any imageset files in \(Parameters.inputPath)")
}
@AliSoftware
Copy link

Hi @KingOfBrian,

You might be interested to know that I developed a similar tool to generate enums for assets — which actually can also generate enums for various other stuff like UIStoryboards and Localizable.strings, etc…

Anyway, nice to see that we had a similar idea, great minds think alike 😉
Don't hesitate to make suggestions or PR to my code if you see anything that could be improved)

@KingOfBrian
Copy link
Author

Hey @AliSoftware -- That looks awesome! Will definitely point people in that direction instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment