App icons are the first point of engagement for your users, an effective tool to catch their attention, and keep them away from exploring other potential options. Having alternative icon options is a great way to bring some personality to your app, and it’s also fairly simple to set up.

Prerequisite

The ability to change app icons has been present since iOS 10.3, so please make sure you have a recent build of Xcode.

To get started, you will first need some icons. I like to use Figma to design mine, and there is an extension called “App Icon Toolkit” which exports your icon with the correct sizes as well as naming convention.

Xcode

In Xcode, I have created a new group called “AlternativeIcons” to organize my icons. Each image should be available in both 2x (120 x120) and 3x (180 x 180) sizes, 1x size is optional. Please ensure to use the @2x and @3x naming convention that will allow iOS to automatically select the correct icon with the best resolution for the user’s device.

The example project is called "AlternativeIcons", you'd create the folder "AlternativeIcons" within the structure of your Xcode project.

Important: Please ensure that these icons do not go inside the Asset catalogue.

Implementation

Next, we are going to create another Swift file called IconManager. In this file, we will create a class called IconManager that will contain three things - a constant, an enum, and a function.

public class IconManager {
    
    private let application = UIApplication.shared
    
    public enum AppIcon: String { // 1
        case charmanderIcon
        case pikachuIcon
    }
   
    public func changeAppIcon(to appIcon: AppIcon?) { // 2
    	let newIcon = appIcon ? appIcon.rawValue : nil // 3
        application.setAlternateIconName(newIcon) // 4
    }
}
  1. We're creating an Enum for type-safety., with the same naming convention, as in the .plist file, to reference to names of the files.
  2. The public method allows for consumers to switch the App Icon based on the enum's raw value.
  3. First we're checking if we have a new icon. nil is a valid option to switch back to the default icon.

Property List

Next, go to the project navigator, right click on the Info.plist file, and choose "Open as Source Code". Scroll to the bottom until you see:

</dict>
</plist>

Directly before </dict>, add the following code snippet.

<key>CFBundleIcons</key>
    <dict>
    
        <key>CFBundlePrimaryIcon</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>58-1</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
        
        <key>CFBundleAlternateIcons</key>
        <dict>
        
            <key>charmanderIcon</key>
            <dict>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>charmander</string>
                </array>
                <key>UIPrerenderedIcon</key>
                <false/>
            </dict>
            
            <key>pikachuIcon</key>
            <dict>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>pikachu</string>
                </array>
                <key>UIPrerenderedIcon</key>
                <false/>
            </dict>
            
        </dict>
    </dict>

The key CFBundlePrimaryIcon refers to your default icon, the key CFBundleIconFiles refers to the file that contains your primary icon, and in between the two <string> tags should be the name of your primary icon.

You can find this by going to your assets folder - AppIcons - find the 2x iPhone app icon  - right click -  select show in finder. Everything before .png should be the name of your image, excluding the 1x / 2x/ 3x naming convention. For example, my files are named 58-1@2x.png, so I would put 58-1 between the <string> tags.

Moving on to CFBundleAlternateIcons.  In the example XML, I used the references charmanderIcon and pikachuIcon as keys.

In IconManager.swift, in changeAppIcon() function, I am setting the icon names as raw value of each case. As such, we have to use the same reference name inside the Info.plist file, so Xcode knows what to look for.

The same name that you gave to the icons inside AlternativeIcons will go in between the <string> tags.

Action to change the Icon

Lastly, we need to add an action to call the IconManager's functionality and implement the Icon switch. One option would be to add a Button and the sample code below.

private let iconManager = IconManager() // 1

@IBAction func defaultIconTapped(_ sender: Any) {
    iconManager.changeAppIcon(to: nil)
}

@IBAction func charmanderTapped(_ sender: Any) {
    iconManager.changeAppIcon(to: .charmanderIcon)
}

@IBAction func pikachuTapped(_ sender: Any) {
    iconManager.changeAppIcon(to: .pikachuIcon)
}
Consumer implementation of the new IconManager
  1. First we need access to the IconManager, you may choose dependency injection or directly create an instance where you need it.
  2. The remainder of the code is fairly self explanatory. We have 3 different hypothetical buttons and are setting the respective Icon.

Result

When you run your project and tap on each alt icon button, you should see a pop up alert notifying you, that the icon has been changed successfully.

GitHub