閱讀239 返回首頁    go 技術社區[雲棲]


改變iOS app的icon(iOS10.3)

改變iOS app的icon

官方

iOS10.3新增了可以讓開發者去更改app的icon,接下來看看怎麼更改。
官方API給的東西很少,隻是介紹了一個實例方法:

open func setAlternateIconName(_ alternateIconName: String?, completionHandler: ((Error?) -> Swift.Void)? = nil)

根據傳入的參數可知,我們隻需要傳入備用icon名字即可,然後在回調裏麵拿到修改的結果,成功的話error為空,不成功則返回相應的錯誤信息(可以使用error!.localizedDescription來打印查看錯誤信息)。如果失敗的話,alternateIconName屬性不變。這裏注意:

如果當期app使用的icon是備用的icon,那麼這個屬性的值就是當前icon的名字,這個名字是在Info.plist裏麵設置的名字,如果當前app展示的是主要(primary)的icon,那麼這個值為nil。

這裏需要注意兩點:
1. 當前設備的係統版本。這裏的所有api都是10.3才能使用的。
2. 當前app是否支持備用icon。使用supportsAlertnateIcons屬性判斷。隻有為true的使用才能去更改。
API中還有一句話比較關鍵:

你必須在Info.plist裏麵使用CFBundleIcons聲明當前app的primary和alternate icon。這裏如果不了解可以往下看,先忽略。

具體的Info.plist裏麵的字段含義這裏就不在一一說明,詳情可了解這裏

總之官方API上麵我隻找到了這麼多。然而給我的感覺反倒一臉懵逼,完全搞不懂下麵的Info.plist怎麼設置。因此有了下麵的序文。

個人理解

在剛才的Info.plist key介紹裏麵,我們先看一下其他的小知識。
我們都知道在Info.plist裏麵有個Bundle display name,也就是設置app在桌麵顯示的名字。此時如果我們先不管這個key,我們繼續在Info.plist裏麵添加CFBundleDisplayName,你會收到這樣一個提示:

The key you entered is already present in the dictionary.do you want to replace the existing key/value pair?

但是看一下Info.plist字典中的key,並沒有CFBundleDisplayName,替換後發現,原來它就是Bundle display name。也就是說,Info.plist裏麵的Key在Xcode中顯示的並不是Key,而是Xcode name。如下圖:
Snip20170405_2.png

這個是從官方API上截的圖,其實這些Key都有對應的Xcode name,也就是在Xcodes裏麵我們能看到的key。其實也很簡單,如果你把Info.plist使用源碼形式打開(右擊—>Open as —>Source code),你就會發現這裏寫的key就是上麵列出來的key。

先看看我在網上查資料設置的Info.plist:
Snip20170405_1.png
這裏的CFBundleIconFiles是備用icon的名字。下麵的Primary Icon是默認的icon。源代碼就是:
Snip20170406_2.png
其中CFBundleIcons對應的就是Icon files(iOS 5),CFBundleIconFiles就是Primary Icon。
先看一下CFBundleAlternateIcons。這個CFBundleAlternateIcons key所對應的value在iOS裏麵是一個字典,例如:
Snip20170406_3.png
每個字典的key是備用icon的名字,這個也是你傳入到

IApplication.shared.setAlternateIconName(iconName) { (error) in
            if (error != nil) {
                self.aler(str: (error!.localizedDescription))
            }else {
                self.aler(str: "修改成功")
            }
        }

裏麵的iconName。其中的字典對應值解釋如下:
Snip20170406_4.png
CFBundleIconFiles:這個是一個String的數組,裏麵每個元素都是icon 的名字,你可以添加多個不同大小的icon來支持iPhone,iPad。
UIPrerenderedIcon:指定應用程序的圖標是否包含閃光效果(shine effect),如果icon已經有這個效果,就把這個屬性設置為YES來防止係統再次添加相同效果。如果設置為NO(默認值),iOS係統會自動添加這個效果。**然而,我並沒有測試出來這個效果!!**
這裏還要注意一下:Primary Icon的Item 0的name也可以不填寫,蘋果官方文檔也沒有具體說名字這個要怎麼去填寫,隻是說如果你想使用CFBundlePrimaryIcon鍵值定義的icon,直接使用將setAlternateIconName的參數alternateIconName寫成nil就行。在屬性列表裏麵直接不填寫就行(即把AppIcon60x60刪掉)

自己新建一個項目實現

自己實現需要注意兩個問題:
1. Info.plist怎麼設置?
2. 備用圖標icon放到哪裏?

首先來設置Info.plist。
按照蘋果官方的API說法,那就先在Info.plist裏麵添加CFBundleIcons。但是查看了一下Key和Xcode name對應的表格,CFBundleIcons對應的是None,那就直接添加CFBundleIcons吧。點擊Information Property List後麵的加號,輸入CFBundleIcons,當點擊Enter鍵的時候,你會驚奇發現:你添加的CFBundleIcons變成了Icon files(iOS 5)字典。看看CFBundleIcons的官方API:
Snip20170406_6.png
根據英文意思可以知道:該key包含了所有app使用的icons信息。新建的是這樣的:
Snip20170406_8.png
可知默認的包含了CFBundlePrimaryIcon和UINewsstandIcon。裏麵沒有CFBundleAlternateIcons,(我理解的應該是蘋果不太想支持用戶添加備選icon,所以才沒有)。這裏不過多介紹UINewsstandIcon了,它應該是在NewStand上展示的吧,不太清楚,想了解可以看API,裏麵介紹了。
現在把NewStand Icon刪除,添加CFBundleAlternateIcons。添加後如圖所示:
Snip20170406_11.png
但是看官方API對CFBundleAlternateIcon的介紹裏麵,並沒有UINewstandBindingType和UINewsstandBindingEdge,隻有這個:
Snip20170406_12.png
也就是官網所說的隻有CFBundleIconFiles和UIPrerenderedIcon,那就刪了多餘的那兩個UINewstandBindingType和UINewsstandBindingEdge。然後添加UIPrerenderedIcon:
Snip20170406_14.png。按照蘋果的說法,把備用圖標的名字放到Items0裏麵。我們先直接在左側導航中加入兩張圖片:newicon@2x.pngnewicon@3x.png,一個120 * 120,一個180 * 180。
但是看到上圖說的設置,跑起來運行代碼:

    @IBAction func changeToNewIconAction(_ sender: Any) {
        if !checkSupportChangeIcon() {
            return
        }
        if !UIApplication.shared.supportsAlternateIcons {
            return
        }
        changeToIcon("newicon")

    }
    //MARK: check system version
    func checkSupportChangeIcon() -> Bool {
        let deviceVersion = UIDevice.current.systemVersion
        if deviceVersion.contains("10.3") {
            return true
        }
        return false
    }
    //MARK: change to icon message
    func changeToIcon(_ iconName: String?)  {

        UIApplication.shared.setAlternateIconName(iconName) { (error) in
            if (error != nil) {
                self.aler(str: (error!.localizedDescription))
            }else {
                self.aler(str: "修改成功")
            }
        }



    }
    //MARK: alert message
    func aler(str: String) {
        let alert = UIAlertController.init(title: "提示", message: str, preferredStyle: .alert)
        let okAction = UIAlertAction.init(title: "ok", style: .cancel) { (action: UIAlertAction) in
            print("關閉彈出框")
        }
        alert.addAction(okAction)
        self.present(alert, animated: true, completion: nil)
    }

結果卻是:

The file doesn't exist

看了一下官方API對CFBundleAlternateIcons的介紹,裏麵有一句話:

In iOS, the value of the key is a dictionary. The key for each dictionary entry is the name of the alternate icon, which is also the string you pass to the setAlternateIconName:completionHandler: method of UIApplication when changing icons. The value for each key is a dictionary containing the keys in Table 5

意思是這個CFBundleAlternateIcons中的字典的key是備用icon的名字,因此需要這樣修改:
Snip20170406_15.png
也就是CFBundleAlternateIcons字典裏麵的key是備用icon的名字,然後以名字為key的字典裏麵又包含了CFBundleIconFiles和UIPrerenderedIcon。
這樣設置之後再次運行你會發現成功更改了icon。
這樣就成功地改變了icon。
關於Primary Icon,直接不用設置Icon files就好了,如果你想設置為默認的icon,就在setAlternateIconName裏麵傳入nil就好了。這個時候Info.plist源碼長這樣:
Snip20170406_16.png
在Property List裏麵,Primary Icon的Icon already includes gloss effects就是UIPrerenderedIcon,它的設置為false。(**這裏的光澤效果也是沒有測試出來有什麼不一樣**)
接下來看看備用icon是在哪裏放著呢?
開始的時候直接放到這裏:
Snip20170406_17.png
發現是OK的,可以正常顯示。
那麼放到Assets.xcassets裏麵呢?放到Bundle裏麵呢?接下來將每個case都進行測試:

  • 放到Assets.xcassets裏麵。新建一個普通的Image set,然後將圖片放到裏麵,效果如圖所示: Snip20170406_18.png 經過測試發現,這樣放置是無法正常改變appicon的。但是運行結果沒有任何錯誤,而且係統提示裏麵加載的也是新的app icon: IMG_0022.PNG
  • 放到Assets.xcassets裏麵,並且新建的icon,如圖: Snip20170406_19.png 運行依然設置不成功。沒有錯誤提示
  • 放到一個新建的Bundle裏麵。如圖所示:。 Snip20170406_20.png 運行結果依然是沒有成功更改。沒有錯誤提示。

所以經過測試,發現隻有放到導航裏麵的圖片才可以更改成功。在蘋果qa裏麵看到過一個場景,他們是直接在導航新建了一個文件夾,然後將圖片放到裏麵,然後使用。這裏也推薦建立文件夾放入圖片,然後使用

另外,關於icon大小,可以參見這裏

最後告訴大家一個不使用Asset來配置Icon的方法:直接在Info.plist下麵這樣寫:
Snip20170406_22.png
這個是通用的,可以直接設置iPhone和iPad的icon。其實這裏也是想告訴大家:如何在CFBundleIconFiles裏麵去添加圖片數組:

 <key>CFBundleIconFiles</key>
            <array>
                <string>Icon-Small</string>
                <string>Icon-Small-40</string>
                <string>Icon-Small-50</string>
                <string>Icon</string>
                <string>Icon-60</string>
                <string>Icon-72</string>
            </array>
備注
  1. 如果有什麼疑問歡迎留言提問。或直接加群:206613455
  2. 源碼地址:https://github.com/ScottZg/iOSChangeAppIcon

最後更新:2017-04-07 21:25:10

  上一篇:go Copycat - Overview
  下一篇:go Copycat - 狀態