SwiftGen is a code generator tool that allows us to generate Enums from images, storyboards, Localizable.strings, etc.

To understand the real value that SwiftGen can bring to tour projects we need to revisit first how resources such as images, or storyboards are called, and what are the caveats associated to the usual way in which we use them.

Usual way of using images in Swift:

let logo = UIImage(named: "logoSmall")

The same applies to storyboards:

let storyboard: UIStoryboard = UIStoryboard(name: "TodoDetail", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "DetailTodoViewController") as! DetailTodoViewController

And to localization Strings:

self.title = NSLocalizedString("Appointments for this month", comment: "")

All the examples above have the same problem, we are using hard-coded strings to reference resources be it images, storyboards, etc.

We all made mistakes ...
We all made mistakes …

When we using strings we are vulnerable to typos. If we mistakenly write “Tododetail”, to refer to our “TodoDetail” storyboard, the compiler won’t complain. We will remain ignorant of our mistake; in the worse case scenario, the bug will be discovered by an user when he tries to access that screen, and the application crashes on him.

If we use that same resource from many different places in our application the possibilities of introducing such a bug increases.

To resolve that potential issue we could refactor our code like this:

enum ImageAsset : String {
    case logo = "logoSmall"
    case todo_icon = "todo-icon"
    case add_icon = "add-icon"
}

let logo = UIImage(named: ImageAsset.logo.rawValue)

Now every time we need to use the “logo-small” image in our app, we can refer to it as ImageAsset.logo, reducing the use of a string identifier to just one point in the app.

Automating the process with SwiftGen

Applying the above solution manually is time consuming: we must keep track of the changes introduced in the app, to keep our enums up to date. Here is when SwiftGen comes into play: it can scan the code generating automatically Enums for different kind of resources.

The process can be automated even more since we can integrate SwiftGen with XCode so that everytime the project is build, SwiftGen is run, ensuring therefore that our generated code is up to date.

Install SwiftGen

SwiftGen can be installed using Homebrew:

brew update
brew install swiftgen

Integrated SwiftGen with XCode

As I have stated before, the possibility of executing SwiftGen automatically every time we build the project is particularly interesting:

  • Select your project, select your app in the target section
  • Go to the “Build Phases” tab
  • Click “+” and select “New Run Script Phase”

Add your script for the resources you want code generated automatically:

if which swiftgen >/dev/null; then
 swiftgen images -t dot-syntax-swift3 "$PROJECT_DIR/Assets.xcassets" --output "$PROJECT_DIR/Constants/Images.swift"
 swiftgen strings -t dot-syntax-swift3 "$PROJECT_DIR/en.lproj/Localizable.strings" --output "$PROJECT_DIR/Constants/i18n.swift"
else
echo "warning: SwiftGen not installed"
fi

I am using the -t dot-syntax-swift3 switch to generate swift 3 compatible code. Otherwise we will get errors such as this one:

/Users/myuser/Downloads/_PROJECTS/TestTodo/Images.swift:121:18: ‘NSBundle’ has been renamed to ‘Bundle’

Another issue that I found was that SwiftGen generation fails when trying to generate code for images, if there are empty folders in Assets.xcassets.

Other than that everything worked fine, and once SwiftGen has generated the code structures, the only thing left to do is use them 🙂 :

//Images samples
let logo = return UIImage(asset:.logoSmall)
//Localized Strings
self.title = L10n.MonthAppointments.string

Hope it was of help. If you found this post useful, you can subscribe to my blog (click at the follow button at the bottom) so you can be notified of new posts.

Advertisements