How To Change Your App Icon at Build Time

Using Xcode, ImageMagick and shell-scripting, this tutorial demonstrates how to generate app icons at build time based on the current build configuration. By .

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Xcode

After all that image processing work, it’s time to cleanse your palate by working in some familiar territory.

Open Xcode, select File\New\Project…, choose the iOS\Application\Single View Application template, and click Next. Name the project Llama Trot, set the selected language to Swift, and set the device family to Universal. For simplicity, save the project to the desktop.

Your goal is to have Xcode and ImageMagick generate an appropriate icon every time you build the project, based on the selected build configuration.

Xcode has the ability to use run scripts to do things when your project is built. A run script is just a Unix script, like what you’ve already written, that executes every time you run your Xcode project.

Setting Up a Run Script

In your project, select the Llama Trot target, and navigate to Build Phases. Click the + icon and select New Run Script Phase from the popup menu:

Screen Shot 2015-05-10 at 10.53.12 PM

You’ll see the Run Script Phase added to your project’s phases.

Within that run script, the Shell parameter should be auto-set to bin/sh, which means that this script will execute in the bash Unix shell.

Underneath the shell parameter is a box for you to enter your script. Type the line below into that box:

echo "Hello World"

Your new build phase should now look like the following:

Screen Shot 2015-05-10 at 10.54.54 PM

Build and run. You should see absolutely nothing interesting. That’s because the script printed Hello World to your build logs while you weren’t looking.

Navigate to the Report Navigator-that’s the icon on the far right of Xcode’s Navigator Pane-and click on the most recent build report, as shown in the image below. In the wall of text describing all of the work that Xcode does for you when you build a project, you’ll see the text Hello World:

HelloWorld

App Icons

Great, you’ve gotten a script to output Hello World, like you’ve probably done a million times by this point in your career as a developer. Now it’s time to modify the app icons.

Finding the App Icons From Your Script

Add all the app icons to your Images.xcassets asset catalog by navigating to Images.xcassets in Xcode and dragging each icon into it’s appropriate tile in the AppIcon image set:

AppIcon

You’ll also need to put debugRibbon.png and betaRibbon.png in your project’s root directory-the same folder where your project’s .xcodeproj file is.

Screen Shot 2015-05-10 at 10.47.33 PM

In order do anything with the icons, your script needs to know where they are. Replace your run script with the following code:

echo "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
echo "${SRCROOT}"
  1. The first line prints the path to the folder that will contain the final icons after you run your project.
  2. The second line prints the folder path of where your project files are located.

This works by using some of Xcode’s many build settings’ variables.

Run your project and check the build report. You should see the folder path that describes the location of your project’s final products. Under that, you should see the folder path of your project directory:

Paths

Navigate to the first path in Finder and look at what’s in there; you’ll see all of the products of your app, including all of the app icons. This is where you’ll save the icons that ImageMagick modifies.

To see these icons, right-click on the Application icon in that folder, and then select Show Package Contents. For now they look perfectly normal!

Finder

Now navigate to the second folder path that you echoed out. This is just your normal project folder. So where are the app icons?

Go into the folder that has the same name as your project-in this case “Llama Trot”. In there you’ll see Images.xcassets. Open Images.xcasset and you’ll see yet another folder named AppIcon.appiconset.

The app icons are in that folder, and you’ll modify them with ImageMagick. Assuming you saved your project to the desktop and named it Llama Trot, the path to the icons is ~/Desktop/Llama\ Trot/Llama\ Trot/Images.xcassets/AppIcon.appiconset

You’re going to cheat a little bit to get the full path to the initial icons, so replace the last line of your script with:

IFS=$'\n'
echo $(find ${SRCROOT} -name "AppIcon60x60@2x.png")
  1. The first line temporarily sets the IFS-internal field separator-to the newline character. If you don’t do this, the second line will fail because the file name, Llama Trot, contains a space-try commenting out the first line if you’re curious about what happens.
  2. The second line in this command searches the ${SRCROOT} folder recursively for the file AppIcon60x60@2x.png.

By the way, it’s important that you type the line IFS=$'\n' precisely as it appears–no spaces on either side of the = sign.

Run the project, and you’ll see the full path to AppIcon60x60@2x echoed out:

IconLocation

Putting It All Together

The hard work is over. Now it’s time to put everything together and get your script to modify the app icons properly. You’ll start by only modifying AppIcon60x60@2x.png, and then work towards generalizing it for all of the app icons. This means you’ll need to test with a retina @2x iPhone simulator or device-so not the iPhone 6+.

By combining the techniques from ImageMagick and your previous script, you end up with the following script. Make sure to update your script accordingly:

IFS=$'\n'
#1
PATH=${PATH}:/usr/local/bin

#2
TARGET_PATH="${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AppIcon60x60@2x.png" 
BASE_IMAGE_PATH=$(find ${SRCROOT} -name "AppIcon60x60@2x.png") 

#3
convert betaRibbon.png -resize 120x120 resizedBetaRibbon.png 

#4
convert ${BASE_IMAGE_PATH} -fill white -font Times-Bold -pointsize 18 -gravity south -annotate 0 "Hello World" - | composite resizedBetaRibbon.png - ${TARGET_PATH}

Here’s a breakdown of what’s happening:

  1. The build will fail if you omit this line. Your terminal has a variable called PATH that stores a list of default script locations. Terminal looks there first for any commands that aren’t a part of Unix by default. This allows any command located in a directory in PATH to run without specifying the full location of the command. Xcode needs to share the same PATH variable as your terminal. This line adds /user/local/bin to the PATH variable where Homebrew installs its packages.
  2. The next two lines get the location of the app icons, as before, and then they save each path into variables TARGET_PATH and BASE_IMAGE_PATH respectively.
  3. This line sizes the beta ribbon down to the appropriate size
  4. The last line does two things at once. First, it annotates the initial app icon with the text Hello World. The script then pipes into the composite function — that’s what the | symbol is all about — and places the resized beta ribbon on top of it. ImageMagick does this by using a dash “-” instead of the file name. The script saves the result as the product app icon.

Note: App icon names are not arbitrary. The name of the app icons must be like AppIcon60x60@2x.png in the final product. Xcode uses this naming convention to determine which icon to use based on which device is in use.

Run the app and go to your device’s home screen to see the icons for your app; if you’re on the simulator, press Cmd + Shift + H to get to the home screen. You should see a modified icon:

AppIcon60x60@2x