Implementing alternate icons in iOS

Overview of what you need to do to allow users to select custom icons. With common pitfalls and iPad implementation.

So far I have implemented alternate icons in a few apps and since I have met quite a few pitfalls along the way, decided to write up this guide. It will show you exactly what you need to do to have alternative icons and extra steps needed for iPad. Let's go.

Before we start, let's briefly look at what are the individual steps.

  • Prepare icons and add them to project
  • Modify Info.plist to list these icons
  • Implement icon switching in code

Preparing icons

Obviously, if you want to offer alternate / alternative / dynamic icons, I need to first create some 😃 These can be either variants with different backgrounds or entirely different icons.

For iPhone apps you need you need 120x120 and 180x180 pixel files. Preferably PNG.

These files need to be added to group in your project - not in Assets catalog!

Let's use the name "switchBuddyBlueIcon" as an example. We will need this later for Info.plist and code.

For the 120x120 and 180x180 dimensions we would add these files:

  • switchBuddyBlueIcon@2x.png
  • switchBuddyBlueIcon@3x.png

If your app also runs on iPad, you need two additional sizes. This isn't strictly true, but you will be getting App Store Connect emails about "Missing recommended icon".

To avoid this, prepare 152x152 and 167x167 files with names as follow:

  • switchBuddyBlueIcon@2x~ipad.png
  • switchBuddyBlueIcon@3x~ipad.png

Note the "~ipad" in the names.

Modifying Info.plist

The next required step is entry in Info.plist which lists all you alternative icon names.

It looks like this:

(I would recommend opening the file as "Source Code")

<key>CFBundleIcons</key>
<dict>
    <key>CFBundleAlternateIcons</key>
    <dict>
        <key>switchBuddyBlueIcon</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>switchBuddyBlueIcon</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
    </dict>
    <key>CFBundlePrimaryIcon</key>
    <dict>
        <key>CFBundleIconFiles</key>
        <array>
            <string></string>
        </array>
        <key>UIPrerenderedIcon</key>
        <false/>
    </dict>
</dict>

We first have key CFBundleIcons which has CFBundleAlternateIcons key to list all the available alternative icons and also entry for the primary one.

I am using the icon name both for key and value without the extension. So just "switchBuddyBlueIcon". For more icons, you would create new dict entry in the CFBundleAlternateIcons.

To be clear, I am talking about this fragment:

<key>switchBuddyBlueIcon</key>
<dict>
    <key>CFBundleIconFiles</key>
    <array>
        <string>switchBuddyBlueIcon</string>
    </array>
    <key>UIPrerenderedIcon</key>
    <false/>
</dict>

Copy it below the original and change the icon name.

Modifying Info.plist for iPad

Once again, iPad requires extra steps, without these your icons won't change on iPad.

You basically need to copy the CFBundleIcons block and append ~ipad like this:

<key>CFBundleIcons~ipad</key>
<dict>
    <key>CFBundleAlternateIcons</key>
    <dict>
        <key>switchBuddyBlueIcon</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>switchBuddyBlueIcon</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
    </dict>
    <key>CFBundlePrimaryIcon</key>
    <dict>
        <key>CFBundleIconFiles</key>
        <array>
            <string></string>
        </array>
        <key>UIPrerenderedIcon</key>
        <false/>
    </dict>
</dict>

Done!

Changing the icon in code

The methods and properties to work with alternative icons are available on the UIApplication.share property.

To start, you can check if alternative icons are supported:

UIApplication.shared.supportsAlternateIcons

The docs are super brief:

The value of this property is true only when the system allows you to change the icon of your app.

But it doesn't say under which conditions this would be false. Anyway, if you want to be safe, you can check this property before showing user the option to pick alternate icons.

Let's change the icon!

UIApplication.shared.setAlternateIconName("switchBuddyBlueIcon", completionHandler: nil)

And done! System will show the prompt confirming icon change. You can optionally check for errors with the completionHandler but if you did the previous steps correctly, there should be no need.

Setting the icon back to default

Want to reset alternative icon and use the default one? Pass nil as the icon name:

UIApplication.shared.setAlternateIconName(nil, completionHandler: nil)

Indicating which icon is currently selected

As a small UX improvement, I am showing selection indicator for currently active icon in my apps. Some also have app icon in about page footer, where I also display alternative icons if needed.

You can achieve this by checking this property:

UIApplication.shared.alternateIconName

nil means default icon is selected, otherwise it will contain name of the alternate icon.

And that should be everything there is to alternate icons!

Uses: Xcode 12 & Swift 5.3

Filip Němeček profile photo

WRITTEN BY

Filip Němeček @nemecek_f

iOS blogger and developer with interest in Python/Django. Telling other devs' stories with iOS Chat.