【iOS】動態更換圖示

zhang!Peng 丶發表於2018-12-20

iOS 10.3蘋果新增了更換圖示的功能,通過這個功能,我們可以在適當的時候採取特定的方式為我們的App更換圖示。 聽似很好很方便,實則並沒有。原因如下:

  1. 更換的圖示,我們需要預置在專案中
  2. 替換圖示這個功能,一定要經過使用者同意(雖然有跳過這一步的方法,但是不建議使用

雖然我們在使用這個功能時有著種種限制,但是瑕不掩瑜,他同樣為我們的使用者體驗帶來了提升:

  1. 逢年過節想換個應景的App圖示,不用在進行發版了
  2. 公司有個重大活動需要更換圖示,不用擔心活動前不能成功發版上線了

注: 我們更換的不只是APP的圖示,還有通知欄的中的圖示,以及設定介面中的圖示等所有與我們 App 有關的圖示。

開發步驟

準備你要更換的圖示

將我們需要更換的圖示放到我們的專案目錄中(因為放到.xcassets中不管用),圖片的命名建議以下面的方式命名,例如:xx20x20@2x.png,xx20x20@3x.png…這樣在填寫Info.plist時也會省事很多。

icon命名

PS: 其實對於更換的圖示,我們也可以只提供一張,但命名時,我們就不要填寫具體的尺寸了,只保留圖片名字即可,例如:xx@2x.png,xx@3x.png, 但是效果上可能不如準備一整套的效果好。畢竟把一張桌面圖示大小的圖片塞到通知圖示那麼小的框裡,圖片會壓縮。

修改Info.plist

想要實現換圖示的功能,Info.plist 檔案的修改是很重要的一步。

編輯Info.plist

  • CFBundleIcons: 一個字典,包含所有AppIcon資訊,即上圖的Icon files(iOS 5)
  • CFBundlePrimaryIcon: 如果已經在Assets.xcassets中設定了AppIcon,那麼CFBundlePrimaryIcon中的配置會被忽略,Assets.xcassetsAppIcon將會自動配置到CFBundlePrimaryIcon中。
  • CFBundleAlternateIcons: 一個陣列,負責配置可供替換的icon資訊
  • UIPrerenderedIcon: 是否已經預渲染,如果不設定該項或者設為NO。系統會自動為icon進行渲染增加光澤

如果想詳細瞭解CFBundleIcons, CFBundlePrimaryIcon, CFBundleAlternateIcons,請檢視附件2

如果iPad需要也需要更換圖示,那麼我們需要在CFBundleIcons~ipad進行同樣的設定。

注: 不能把圖片放在.xcassets裡面

編寫程式碼

通過檢視文件,我們可以看到下面幾個屬性和方法。

// If false, alternate icons are not supported for the current process.
// 檢查是否支援更換圖示
@property (readonly, nonatomic) BOOL supportsAlternateIcons NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));

// Pass `nil` to use the primary application icon. The completion handler will be invoked asynchronously on an arbitrary background queue; be sure to dispatch back to the main queue before doing any further UI work.
// 更換圖示
- (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 `nil`, the primary application 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));
複製程式碼

系統提供的 API 簡單明瞭,唯一要注意的是下面這個方法。

- (void)setAlternateIconName:(nullable NSString *)alternateIconName completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler
複製程式碼

方法中的alternateIconName引數,是要填寫您在Info.plist 中填寫的名字,如圖二中所示,我們應當在此方法中填寫female或者male1.

程式碼示例

為了方便大家使用,我將更換圖示相關的程式碼已經寫好在下面,如需自取。 也可以訪問 DynamicAppIconDemo,檢視 FSAppIconManager

+ (NSString *)getCurrentAppIconName {
    if (@available(iOS 10.3, *)) {
        return ([UIApplication sharedApplication].alternateIconName.length == 0) ? @"" : [UIApplication sharedApplication].alternateIconName;
    } else {
        // Fallback on earlier versions
        return @"";
    }
}

+ (BOOL)canChangeAppIcon {
    if (@available(iOS 10.3, *)) {
        return [[UIApplication sharedApplication] supportsAlternateIcons];
    } else {
        // Fallback on earlier versions
        return NO;
    }
}

+ (void)changeAppIconWithIconName:(NSString *)iconName completionHandler:(void (^)(NSError * _Nullable))completionHandler {
    if (@available(iOS 10.3, *)) {
        [[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
            if (!error) {
                completionHandler(nil);
            } else {
                completionHandler(error);
            }
        }];
    } else {
        // Fallback on earlier versions
        NSDictionary *userInfo = @{
                                   NSLocalizedDescriptionKey: NSLocalizedString(@"AppIcon change failed", nil),
                                   NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The current system version does not support replacing the AppIcon.", nil),
                                   NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"", nil)
                                   };
        NSError *error = [NSError errorWithDomain:@""
                                             code:34001
                                         userInfo:userInfo];
        completionHandler(error);
    }
}
複製程式碼

下面給出部分 App Icon 相關的資料

App Icon Attributes

Attribute Value
Format PNG
Color space sRGB or P3 (see Color Management)
Layers Flattened with no transparency
Resolution Varies. See Image Size and Resolution
Shape Square with no rounded corners

App Icon Sizes

Device or context Icon size
iPhone 180px × 180px (60pt × 60pt @3x)
120px × 120px (60pt × 60pt @2x)
iPad Pro 167px × 167px (83.5pt × 83.5pt @2x)
iPad, iPad mini 152px × 152px (76pt × 76pt @2x)
App Store 1024px × 1024px (1024pt × 1024pt @1x)

Spotlight, Settings, and Notification Icons

Device or context Spotlight icon size Settings icon size Notification icon size
iPhone 120px × 120px (40pt × 40pt @3x) 87px × 87px (29pt × 29pt @3x) 60px × 60px (20pt × 20pt @3x)
80px × 80px (40pt × 40pt @2x) 58px × 58px (29pt × 29pt @2x) 40px × 40px (20pt × 20pt @2x)
iPad Pro, iPad, iPad mini 80px × 80px (40pt × 40pt @2x) 58px × 58px (29pt × 29pt @2x) 40px × 40px (20pt × 20pt @2x)

Notice:

Don’t add an overlay or border to your Settings icon. iOS automatically adds a 1-pixel stroke to all icons so that they look good on the white background of Settings.

  1. Human Interface Guidelines - App Icon
  2. CFBundleIcons,CFBundlePrimaryIcon,CFBundleAlternateIcons

title: 【iOS】動態更換 App 圖示

author: zhangpeng

date: 2018.07.10

GitHub: github.com/fullstack-z…

相關文章