替换应用图标的实现,非常简单,不过为了防止以后做类似需求时忘记步骤,做个记录。

一、导入图标资源

准备应用图标资源,放在 group 目录下,注意不是导入 assert 文件夹。iPhone 图标提供60*60的@2x 和@3x的图标,@2x 应用图标大小为120*120,@3x 图标大小为180*180,如果需要支持 iPad,还需要76*76的@1x和@2x,83.5*83.5的@2x。命名保持统一,可以用图标工场生成,也可以让设计给。最终导入效果如下:

image-20210708180124063

二、修改 plist 文件

用 source code模式打开 app 的 plist 文件,设置对应的 key-value:

<key>CFBundleIcons</key>     // 应用图标
<dict>
    <key>CFBundleAlternateIcons</key>   // 可替换的图标
    <dict>
        <key>logokuan</key>							// 代码中使用的图标名
        <dict>
            <key>CFBundleIconFiles</key>     // 图标名对应的图标资源	 
            <array>
                <string>logokuan-60</string>
                <string>logokuan-76</string>
                <string>logokuan-83.5</string>
            </array>
        </dict>
    </dict>
    <key>CFBundlePrimaryIcon</key>					// 应用主图标,可以不进行操作,默认会取 assets 内的 icon
    <dict>
        <key>CFBundleIconFiles</key>				// 图标资源
        <array>
            <string></string>
        </array>
        <key>CFBundleIconName</key>			   // 图标名  		
        <string></string>
        <key>UIPrerenderedIcon</key>       // 是否带光泽效果 (ios7 以上废弃)
        <false/>
    </dict>
</dict>
<key>CFBundleIcons~ipad</key>							// ipad图标配置,和上面的类似
<dict>
    <key>CFBundleAlternateIcons</key>
    <dict>
        <key>logokuan</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>logokuan-60</string>
                <string>logokuan-76</string>
                <string>logokuan-83.5</string>
            </array>
        </dict>
    </dict>
    <key>CFBundlePrimaryIcon</key>
    <dict>
        <key>CFBundleIconFiles</key>
        <array>
            <string></string>
        </array>
        <key>CFBundleIconName</key>
        <string></string>
        <key>UIPrerenderedIcon</key>
        <false/>
    </dict>
</dict>

设置完成之后,使用 property list 查看配置如下:

image-20210709100934324

到了这里,我们的配置工作已经完成了,接下来就是在代码中实现。

三、代码实现替换逻辑

代码非常简单,系统给我们提供了如下 API:

    // If false, alternate icons are not supported for the current process. 是否支持更改图标
    @available(iOS 10.3, *)
    open var supportsAlternateIcons: Bool { get }

    
    // 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.  设置应用图标,为 nil 时使用主图标。
    @available(iOS 10.3, *)
    open func setAlternateIconName(_ alternateIconName: String?, completionHandler: ((Error?) -> Void)? = nil)

    
    // If `nil`, the primary application icon is being used. 获取当前的应用图标名称,为 nil 时为主图标。
    @available(iOS 10.3, *)
    open var alternateIconName: String? { get }

根据以上的代码就可以实现替换的功能,需要注意的一点是在setAlternateIconName(_ alternateIconName: String?, completionHandler: ((Error?) -> Void)? = nil) 闭包内如果需要对 UI 进行刷新或者其他的处理,需要回到主线程操作。