Changing icon on iOS10.3 with push notifications

iOS 10.3 brings the ability to change iOS app icon. Let's combine this with push notifications!

Looks like magic? Let's implement this!

XCode setup

First of all you need to add new icon images to your project and to Info.plist file.

Locate "CFBundleIcons" (a.k.a. "Icon files (iOS 5)) in your Info.plist file and add "CFBundleAlternateIcons" property there. See the full set-up on the screenshot below.

Let's add some code to push notifications handler onPushReceived function to change the app's icon. In this example we will use "changeIcon" custom data parameter to set the icon:

    func onPushReceived(_ pushManager: PushNotificationManager!, withNotification pushNotification: [AnyHashable : Any]!, onStart: Bool) {
        let customData = PushNotificationManager.push().getCustomPushData(asNSDict: pushNotification)
        
        if #available(iOS 10.3, *) {
            let icon = customData?["changeIcon"]
            
            if var icon: String = icon as? String {
                if icon == "nil" {
                    icon = ""
                }
                
                if UIApplication.shared.applicationState != UIApplicationState.active {
                    var observer: NSObjectProtocol?
                    observer = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationDidBecomeActive,
                                                                      object: nil,
                                                                      queue: OperationQueue.main,
                                                                      using: { (notification) in
                                                                        NotificationCenter.default.removeObserver(observer!)
                                                                        UIApplication.shared.setAlternateIconName(icon, completionHandler: { (error) in
                                                                            if let error = error {
                                                                                print("Set icon error = " + error.localizedDescription)
                                                                            }
                                                                        })
                    })
                } else {
                    UIApplication.shared.setAlternateIconName(icon, completionHandler: { (error) in
                        if let error = error {
                            print("Set icon error = " + error.localizedDescription)
                        }
                    })
                }
            }
        }
    }
- (void)onPushReceived:(PushNotificationManager *)pushManager withNotification:(NSDictionary *)pushNotification onStart:(BOOL)onStart {
    NSDictionary *data = [[PushNotificationManager pushManager] getCustomPushDataAsNSDict:pushNotification];
    
    if (@available(iOS 10.3, *)) {
        NSString * icon = [data objectForKey:@"changeIcon"];
        if(icon != nil) {
            if([icon isEqualToString:@"nil"])
                icon = nil;
            
            NSLog(@"icon is: %@", icon);
            
            if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
                __block __weak id observer = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
                    [[NSNotificationCenter defaultCenter] removeObserver:observer name:UIApplicationDidBecomeActiveNotification object:nil];
                    [[UIApplication sharedApplication] setAlternateIconName:icon completionHandler:^(NSError * _Nullable error) {
                        NSLog(@"Set icon error = %@", error.localizedDescription);
                    }];
                }];
            } else {
                [[UIApplication sharedApplication] setAlternateIconName:icon completionHandler:^(NSError * _Nullable error) {
                    NSLog(@"Set icon error = %@", error.localizedDescription);
                }];
            }
        }
    }
}

Sending a push to trigger icon change

Now go to the control panel and let's test this! Set the push title:

Set the custom data. In this case I'll use "xmas_sale" as icon (see Info.plist setup):

Done!