There will always be a demand for dynamic App ICONS: some users like to “beautify” their phones. To what extent users prefer beautification depends on individual needs. Some users want to customize the App icon, so the major iPhone forums have a way to change the App icon without jailbreaking; Some users want the App icon to “move” (for example, the system application clock), so it is really difficult not to cross the line.

But today we want to talk about apple’s official support for dynamic App ICONS.

This series of articles

  1. IOS Dynamic App icon Replacement (1) : Basic use
  2. IOS Dynamic App icon Replacement (2) : No dialog box is displayed. Replace the App icon
  3. IOS Dynamic App icon replacement (3) : Dynamically download the App icon for replacement

The Demo presentation





DynamicAppIconDemo1

Demo address: github.com/maybeisyi/C…

The corresponding project of this article is: DynamicAppIcon (1)

As you can see in the Demo, you can update the App icon without reinstalling the App. However, a prompt will pop up to inform the user that the current icon has been changed, and of course the next article will break this “limit”.

Scenarios in which the function is applied

1. Switch the day/night mode. Switch the App icon while switching the main color of the App.

2, all kinds of skin themes (taobao can be skin), with App icon to replace a piece.

3. Use App ICONS to express specific functions, such as the current weather in Demo.

4. Icon promotion hints, such as Taobao jingdong special festivals: 11.11, 6.18, change the App icon in advance.

Of course, this feature (API) is currently only supported on iOS10.3 or higher, so it should only be used as an additional feature. Here’s how to use the code to do this.

The API with a document

API methods

@interface UIApplication (UIAlternateApplicationIcons)
// If the value is NO, the current process does not support icon replacement
@property (readonly, nonatomic) BOOL supportsAlternateIcons NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));

// Passing nil means use the main icon. The completed operation will be executed asynchronously in any background queue; If you need to change the UI, make sure you do it in the main queue.
- (void)setAlternateIconName:(nullable NSString *)alternateIconName completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));

// If alternateIconName is nil, the main icon is being used.
@property (nullable, readonly, nonatomic) NSString *alternateIconName NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
@endCopy the code

There are three methods in total, which are neat and clear, but looking at these three apis, it is not clear how alternateIconName is linked to the app icon, so we need to read the documentation further.

The document

Shift +command+0

  1. supportsAlternateIcons




supportsAlternateIcons Document

The value is YES only if the system allows you to change your app icon. You need to declare replaceable app ICONS in the CFBundleIcons key in the info.plist file.

  1. alternateIconName




alternateIconName Document

When the system displays your changed app icon, this value is the icon name (defined in info.plist). This value is nil if the main icon is displayed.

  1. setAlternateIconName:completionHandler:




setAlternateIconName Document

AlertnateIconName parameter: This parameter is the name of the app icon that you want to change. It is defined in the CFBundleAlertnateIcons key in your info.plist. If you want to display the primary icon defined with the CFBundlePrimaryIcon key, pass nil. CFBundleAlertnateIcons and CFBundlePrimaryIcon are both defined in CFBundleIcons.

CompletionHandler parameter: This parameter is used to process (replace) the result. When the system tries to change the icon of the app, the result data is passed in this parameter and executed (the execution process is in the queue provided by UIKit, not the main queue). The execution takes one parameter: error. If the app icon was replaced successfully, then this parameter is nil. If an error occurs during the replacement, the object indicates the error message and the app icon remains the same.





setAlternateIconName2 Document

Use this method to change the app icon to a master or interchangeable icon. You can only change supportsAlternateIcons if the return value is YES.

You must declare replaceable app ICONS (main ICONS and replaceable ICONS) in the CFBundleIcons key of the info. plist file. For configuration Information about replaceable ICONS, refer to the description of CFBundleIcons in the Information Property List Key Reference.

The document repeatedly mentions the Info. Plist file and CFBundleIcons, which are the old methods used to configure App ICONS before Xcode6. Later, with the more complete assets.scassets, the configuration of App ICONS has become easier and more complete. But now that the method is back on the table, it must have been the result of a lot of fighting inside Apple. Why did Apple rush to release the API in 10.3 instead of 11? Why doesn’t Apple use Assets.scassets to configure App ICONS that can be changed? We don’t know, but we’re sure Apple will be tweaking this configuration in the future.

You can change the configuration method of App icon

Official configuration document





CFBundleAlternateIcons1 Document

This configuration document is quite extensive, so let’s highlight it (ignore the tvOS part, same below) :

  • Info.plist is a dictionary, let’s say NSDictionary *infoPlist.

  • CFBundleIcons is a key in the info. plist dictionary @”CFBundleIcons”.

  • The value of CFBundleIcons is a dictionary.
  • CFBundleIcons can contain the following keys: CFBundlePrimaryIcon, CFBundleAlternateIcons, UINewsstandIcon.

Let’s show the structure of the wrap in code:

NSDictionary *infoPlist;
infoPlist = @{
               @"CFBundleIcons" : @{
                                     @"CFBundlePrimaryIcon" : xxxThe @"CFBundleAlternateIcons" : xxxThe @"UINewsstandIcon" : xxx}};Copy the code




CFBundleAlternateIcons2 Document

This is the configuration document for CFBundleAlternateIcons:

There’s a sentence that’s hard to understand without thinking about it:

In iOS, the value of the key is a dictionary. The key for each dictionary entry is the name of the alternate icon

Translation:

The corresponding value for this key is the dictionary, and the key for each dictionary entry is the name of the alternate icon.

The underlying data structure of CFBundleAlternateIcons is not immediately clear from this statement. What this actually means is:

The value of that key is a dictionary, and each key in that dictionary is a dictionary, and those keys are the names of alternate ICONS.

Let’s list the rest of the highlights:

  • CFBundleAlternateIcons has a value ofThe dictionary(in iOS), assumingNSDictionary * alertnateIconsDic.
  • AlertnateIconsDic keys, both of themThe name of the alternate icon, it is assumed that for@"newAppIcon"and@"newAppIcon2".
  • @"newAppIcon"Is a value that contains CFBundleIconFiles and UIPrerenderedIconThe dictionary.
  • The value of CFBundleIconFiles is either a string or an array (the contents of an array are also strings). The string contains the names of alternate ICONS in each size.
  • UIPrerenderedIcon value is a BOOL. The effect of this key is no longer valid in iOS7 and beyond. In iOS6, app ICONS can be rendered with highlighting. So we don’t have to worry about this value right now.

Let’s show the structure of the value of CFBundleAlternateIcons in code:

@"CFBundleAlternateIcons" : @{
                               @"newAppIcon" : @{
                                                 @"CFBundleIconFiles" : @[
                                                                            @"newAppIcon"
                                                                         ],
                                                 @"UIPrerenderedIcon" : NO
                                                },
                               @"newAppIcon2" : @{
                                                 @"CFBundleIconFiles" : @[
                                                                            @"newAppIcon2"
                                                                         ],
                                                 @"UIPrerenderedIcon" : NO}}Copy the code

Actual configuration file (info.plist)

The actual configuration of info.plist looks something like this:





Info.plist1

Of course, drag in the corresponding App icon:





Various weather App ICONS

However, we seem to be missing the main App icon, which is normally our icon. According to the document, we need to configure the corresponding content of CFBundleIcons corresponding to the main icon CFBundlePrimaryIcon in CFBundleIcons, but in fact, we still use the old method to configure AppIcon in Assets.xcassets and fill the corresponding size with the corresponding image. Why is it possible to configure the main icon this way? Let’s take a look at some famous electricity ipa (package) on the AppStore to download the Info. Plist (located in the Payload/XXXXXX/Info. The plist) :





Info.plist of well-known e-commerce

Of course, you can also check the package in your own App. The system will actually convert the AppIcon configured in Assets.xcassets to CFBundlePrimaryIcon in info. plist. So the configuration of our main icon remains the same as before.

Other notes:

  • File extensions, such as @2x and @3x, can either be left out altogether, and the system will automatically find the right size. To do this, you need to write the extension of each icon, as shown above, and there is a separate Demo example of how to add multi-sized ICONS in the Demo of this series.
  • For the iPad version, if you want to change ICONS, you need to set them again in CFBundleIcons ~ for iPad.