Normally, if you need to programmatically create a `UIImage` for an image in your asset catalog, you’re stuck with the stringly typed method which returns an optional:
if let logoImage = UIImage(named: "logo") { // Do something with logoImage}
This is unfortunate for a few reasons:
1. We know the image is there, so it shouldn’t be optional.
2. We have to remember the exact name of the image asset we need.
3. It’s easy to make a typo.
4. If someone ever changed the name of the asset in the asset catalog or removed the asset, your code would still compile, but your image would be nil.
To avoid all this, we can use a command line tool called SwiftGen to automatically generate code for an enum defined inside of a UIImage extension which has cases for every asset. The enum has a non-optional `image` var you can use to get a UIImage for that asset. Using this generated code, it’s really easy to instantiate non-optional UIImage instances for assets:
let logoImage = UIImage.Asset.Logo.image
Furthermore, we can have SwiftGen run every time we build the app in order to keep the generated code up to date. In fact, we can have it update the code before compile time. This means if you’re using an asset in your code and then someone deletes the asset from the catalog or changes the name of the asset, your code won’t compile.
Here is an example of the generated code:
extension UIImage { enum Asset: String { case Help = "help" case Logo = "logo" case Search = "search" var image: UIImage { return UIImage(asset: self) } } convenience init!(asset: Asset) { self.init(named: asset.rawValue) }}
At this point, you may be yelling “Hey, wait! I see an exclamation mark! That’s bad!” — and yes, the generated code includes an implicitly unwrapped failable initializer. In this case, however, it’s completely safe because the image is guaranteed to exist since the Asset enum is generated prior to compile time.
Below is a step-by-step guide which explains how you can set up SwiftGen to generate this UIImage asset code for your project.
Step-by-step guide
Add a New Run Script Phase:
1. Select your main target.
2. Select the “Build Phases” tab.
3. Click on the small “+” icon and select “New Run Script Phase”.
Enter the Script Contents
Add the script below:
swiftgen images --output $TARGET_NAME/UIImage+Assets.swift .if [[ $? != 0 ]] ; then cat << EOMerror: Failed to run the swiftgen command. If you do not have swiftgen installed, you can install it via homebrew:$ brew update$ brew install swiftgenFor more information, visit 'https://github.com/AliSoftware/SwiftGen'.EOM exit 1fi
Move Prior to the Compile Sources Phase
Move this new phase above the “Compile Sources” phase:
Generate the File and Add it to the Project
1. Install swiftgen on any mac you’ll be building your project on.
brew updatebrew install swiftgen
2. Go to Xcode and build your project (Command-B).
Go to File > Add Files to “MyProject”… and select the UIImage+Assets.swift file to add it to your project.