How to change an iOS application icon programmatically?

In iOS 10.3, Apple launches a cool function so that developers are able to programmatically change the app icon. In Apple's UIApplication API document, there are 3 things worth a glance:

//A Boolean value indicating whether the app is allowed to change its icon. To make it true, we need to set up alternative icons in Info.plist file.
var supportsAlternateIcons: Bool

//The name of the icon being displayed for the app. Notice that it is nil when app is displaying its primary icon.
var alternateIconName: String?

//Changes the app's icon. If we set the icon name to nil, the app will display its primary icon.
func setAlternateIconName(String?, completionHandler: ((Error?) -> Void)? = nil)

1. Prerequisite

  • Set target to minimum iOS 10.3
  • Add default AppIcon in Assets.xcassets
  • Add your Alternate icons under your project directory (assets seems not to work)

2. Setup Info.plist

  • Add Icon files (iOS 5)/CFBundleIcons to the Info.plist
  • Add CFBundleAlternateIcons as a Dictionary, it is used for alternative icons
  • Set 3 dictionaries under CFBundleAlternateIcons, they are correspond to "AppIconAlternate1", "AppIconAlternate2", and "AppIconAlternate3"
  • For each dictionary, create one properties  CFBundleIconFiles as Array. The array value for key CFBundleIconFiles includes the icon files.

Info.plist screenshot

Info.plist source code

<key>CFBundleIcons</key>
<dict>
	<key>CFBundleAlternateIcons</key>
	<dict>
		<key>AppIconAlternate1</key>
		<dict>
			<key>CFBundleIconFiles</key>
			<array>
				<string>AppIconAlternate1</string>
			</array>
		</dict>
		<key>AppIconAlternate2</key>
		<dict>
			<key>CFBundleIconFiles</key>
			<array>
				<string>AppIconAlternate2</string>
			</array>
		</dict>
		<key>AppIconAlternate3</key>
		<dict>
			<key>CFBundleIconFiles</key>
			<array>
				<string>AppIconAlternate3</string>
			</array>
		</dict>
	</dict>
	<key>CFBundlePrimaryIcon</key>
	<dict>
		<key>CFBundleIconFiles</key>
		<array>
			<string></string>
		</array>
		<key>UIPrerenderedIcon</key>
		<false/>
	</dict>
	<key>UINewsstandIcon</key>
	<dict>
		<key>CFBundleIconFiles</key>
		<array>
			<string></string>
		</array>
		<key>UINewsstandBindingEdge</key>
		<string>UINewsstandBindingEdgeLeft</string>
		<key>UINewsstandBindingType</key>
		<string>UINewsstandBindingTypeMagazine</string>
	</dict>
</dict>

3. Code

Let us assume we have 4 buttons in a view. Tap any of them would make the app to display a correspond icon. Here is the sample code:

@IBAction func appIcon1Tapped(_ sender: UIButton) {
    changeIcon(to: "AppIconAlternate1")
}

@IBAction func appIcon2Tapped(_ sender: UIButton) {
    changeIcon(to: "AppIconAlternate2")
}

@IBAction func appIcon3Tapped(_ sender: UIButton) {
    changeIcon(to: "AppIconAlternate3")
}

@IBAction func resetAppIconTapped(_ sender: UIButton) {
    //Set the icon name to nil, the app will display its primary icon.
    changeIcon(to: nil)
}

func changeIcon(to name: String?) {
    //Check if the app supports alternating icons
    guard UIApplication.shared.supportsAlternateIcons else {
        return;
    }
    
    //Change the icon to a specific image with given name
    UIApplication.shared.setAlternateIconName(name) { (error) in
        //After app icon changed, print our error or success message
        if let error = error {
            print("App icon failed to due to \(error.localizedDescription)")
        } else {
            print("App icon changed successfully.")
        }
    }
}

4. Demo Video

Ref- Apple Documentation


You've successfully subscribed to Developer Insider
Great! Next, complete checkout for full access to Developer Insider
Welcome back! You've successfully signed in
Success! Your account is fully activated, you now have access to all content.