{"metadata":{"image":[],"title":"","description":""},"api":{"url":"","auth":"required","results":{"codes":[]},"settings":"","params":[],"apiSetting":null},"next":{"description":"","pages":[]},"title":"iOS: Changing Icons with Push Notifications","type":"basic","slug":"changing-icons-with-push-notifications","excerpt":"","body":"Starting in iOS 10.3, Apps are able to maintain a set alternate icons which can be switched by the user at runtime. Imagine being able to theme your App Icon based on your home team in a sports app? Or have an icon change to reflect a Sale or campaign, such as Halloween?\n\n## Setting up the icons\nFor this new API, you unfortunately cannot use your XCAssets folder. You instead have to import icon assets using an older technique, by creating a group under Resources. \n[block:image]\n{\n \"images\": [\n {\n \"image\": [\n \"https://files.readme.io/6c9eb80-Screen_Shot_2017-06-29_at_9.24.03_AM.png\",\n \"Screen Shot 2017-06-29 at 9.24.03 AM.png\",\n 259,\n 365,\n \"#f0f0ef\"\n ],\n \"caption\": \"We've included a minimal set for brevity, you should include all icons for all size iPhones and iPads.\"\n }\n ]\n}\n[/block]\n## Configuring your Property List\nInside your App's `Info.plist` file, add the following config to declare your main icon and it's alternatives. The file name should not include the :::at:::2x/@3x and filetype suffix.\n[block:image]\n{\n \"images\": [\n {\n \"image\": [\n \"https://files.readme.io/0b36996-Screen_Shot_2017-06-29_at_9.28.55_AM.png\",\n \"Screen Shot 2017-06-29 at 9.28.55 AM.png\",\n 666,\n 182,\n \"#cedbec\"\n ]\n }\n ]\n}\n[/block]\n## Triggering icon changes\n\nNow, the final step is to configure your app to change the icon in a reaction to a push. We'll use [Key-Value Payloads](doc:key-value-payloads) to send down the alternate icon's key (the key for the dictionary above) and use the standard api for receiving pushes to react. \n[block:code]\n{\n \"codes\": [\n {\n \"code\": \"- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {\\n NSString *iconName = userInfo[@\\\"icon_name\\\"];\\n if (!iconName) {\\n completionHandler(UIBackgroundFetchResultNoData);\\n return;\\n }\\n \\n\\t // We found this delay necessary in testing\\n [self delay:1.0 closure:^{\\n [self changeIcon:iconName];\\n completionHandler(UIBackgroundFetchResultNewData);\\n }];\\n}\\n\\n- (void)changeIcon:(NSString *)iconName {\\n if (@available(iOS 10.3, *)) {\\n if ([UIApplication sharedApplication].supportsAlternateIcons) {\\n [[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {\\n if (error) {\\n NSLog(@\\\"Error setting icon: %@\\\", error);\\n }\\n }];\\n }\\n else {\\n NSLog(@\\\"I cannot change icons\\\");\\n }\\n }\\n}\\n\\n- (void)delay:(double)delay closure:(void(^)())closure {\\n dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC);\\n dispatch_after(when, dispatch_get_main_queue(), closure);\\n}\",\n \"language\": \"objectivec\"\n },\n {\n \"code\": \"func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {\\n guard let iconName = userInfo[\\\"icon_name\\\"] as! String? else {\\n completionHandler(.noData)\\n return\\n }\\n\\n // We found this delay necessary in testing\\n delay(1.0, closure: {\\n self.changeIcon(iconName: iconName)\\n completionHandler(.newData)\\n })\\n}\\n\\nfunc changeIcon(iconName: String) {\\n if #available(iOS 10.3, *) {\\n if UIApplication.shared.supportsAlternateIcons {\\n UIApplication.shared.setAlternateIconName(iconName) { (err:Error?) in\\n print(\\\"Error setting icon: \\\\(String(describing: err))\\\")\\n }\\n } else {\\n print(\\\"I cannot change icons\\\")\\n }\\n }\\n}\\n\\nfunc delay(_ delay:Double, closure:@escaping ()->()) {\\n let when = DispatchTime.now() + delay\\n DispatchQueue.main.asyncAfter(deadline: when, execute: closure)\\n}\",\n \"language\": \"swift\"\n }\n ]\n}\n[/block]\n## Example\n[block:image]\n{\n \"images\": [\n {\n \"image\": [\n \"https://files.readme.io/d6da21f-IconChangeGif.gif\",\n \"IconChangeGif.gif\",\n 495,\n 880,\n \"#38323f\"\n ]\n }\n ]\n}\n[/block]","updates":[],"order":4,"isReference":false,"hidden":false,"sync_unique":"","link_url":"","link_external":false,"_id":"5e6156bf5e4a51006dcd816f","project":"55e67aaa9cc7c62b00c4a1ea","version":{"version":"1.5","version_clean":"1.5.0","codename":"ST Rebrand","is_stable":true,"is_beta":false,"is_hidden":false,"is_deprecated":false,"categories":["5e6156bf5e4a51006dcd8120","5e6156bf5e4a51006dcd8121","5e6156bf5e4a51006dcd8122","5e6156bf5e4a51006dcd8123","5e6156bf5e4a51006dcd8124","561c61b4ad272c0d00a892df","586c014c0abf1d0f000d04d4","58991d2ad207df0f0002186b","5e6156bf5e4a51006dcd8125","5e6156bf5e4a51006dcd8126","5af0fe494ca2730003cbc98a","5af0fe55ec80af0003804ca2","5e69868cbd5dcb006b35867b","5e6986ca2c6652006791b6e8"],"_id":"5e6156bf5e4a51006dcd818c","project":"55e67aaa9cc7c62b00c4a1ea","__v":2,"forked_from":"5b720760c44b7600034b7a08","createdAt":"2015-09-02T04:27:23.612Z","releaseDate":"2015-09-02T04:27:23.612Z"},"category":{"sync":{"isSync":false,"url":""},"pages":[],"title":"iOS Techniques","slug":"ios-techniques","order":9999,"from_sync":false,"reference":false,"_id":"5e6986ca2c6652006791b6e8","createdAt":"2020-03-12T00:48:10.039Z","version":"5e6156bf5e4a51006dcd818c","project":"55e67aaa9cc7c62b00c4a1ea","__v":0},"user":"55d29988486de50d00327118","createdAt":"2017-06-28T21:52:17.509Z","githubsync":"","__v":0,"parentDoc":null}