To integrate SwiftGen directly in an Xcode project, and make it generate the files every time you build your project, you can simply add a "Run Script Phase" to your Xcode project.
You can read Apple's dedicated documentation which explains how to add a Run Script Phase (with illustrations) here.
In short, it consists of these steps:
- Select the project in the Project Navigator on the left of your Xcode window
- Select your App Target in the list
- Go in the "Build Phases" tab
- Click on the "+" button on the upper left corner and choose "New Run Script Phase"
Then name the script phase anyway you like, and write the script invoking SwiftGen the same way you'd invoke it from the Terminal.
For example, your Script Build Phase should look like this if you integrated SwiftGen via CocoaPods:
"$PODS_ROOT/SwiftGen/bin/swiftgen"
Or like this if you downloaded SwiftGen via the ZIP installation method and unzipped it at the root of your repository:
"$PROJECT_ROOT/SwiftGen/bin/swiftgen"
Or could look like this if you installed swiftgen
system-wide with homebrew (adding some security in case your coworkers didn't install SwiftGen on their machine)
if which swiftgen >/dev/null; then
swiftgen
else
echo "warning: SwiftGen not installed, download it from https://github.com/SwiftGen/SwiftGen"
fi
Note: Those script phase examples above all assume that you're using a swiftgen.yml
config file to configure which SwiftGen subcommand (strings
, fonts
, …) to run, the templates to use, etc
Tip: If you don't use a
swiftgen.yml
config file, first I'd strongly suggest you to use one 😉 but if you still want to invoke SwiftGen multiple times, one subcommand at a time, I'd suggest to use/bin/sh -e
(so add the-e
flag) in the "Shell" field of your Build Phase, so that the build phase will fail as soon as one of the SwiftGen subcommands fails. Otherwise your Build Phase's exit code will only reflect the exit code of the last command of the script, so your Build Phase could be considered to pass even if one of the command except the last failed.
When adding SwiftGen as a build phase in your project, if instead of using a Config file you invoked subcommands from the command line, then sometimes builds can cancel because Xcode doesn't like source code changes happening mid-build. It can also cause issues with IBDesignable
views triggering looping builds when opening storyboards.
To avoid this, we highly recommand using a swiftgen.yml
configuration file instead of invoking the subcommands directly from the command line, or if you still want to invoke subcommands from the command line, be sure to use --output
to specify the output file to write (instead of a > output-file.swift
redirection for example). Doing this allows SwiftGen to avoid re-writing the file to disk if the content is not modified.
Typically don't use:
swiftgen xcassets Resources/Images.xcassets -t swift4 > "Constants/Assets+Generated.swift"
But use:
swiftgen xcassets Resources/Images.xcassets -t swift4 --output "Constants/Assets+Generated.swift"
Or even better, just use swiftgen
in your Script Build Phase, and specify this in your swiftgen.yml
config file:
xcassets:
inputs: Resources/Images.xcassets
outputs:
templateName: swift4
output: Constants/Assets+Generated.swift
That way, the Constants/Assets+Generated.swift
file will only be overwritten if the contents of Images.xcassets
has changed since the last generation, and will be kept unmodified otherwise.