改變iOS app的icon(iOS10.3)

改變iOS app的icon

官方

iOS10.3新增了可以讓開(kāi)發(fā)者去更改app的icon,接下來(lái)看看怎么更改。
官方API給的東西很少,只是介紹了一個(gè)實(shí)例方法:

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

根據(jù)傳入的參數(shù)可知,我們只需要傳入備用icon名字即可,然后在回調(diào)里面拿到修改的結(jié)果,成功的話(huà)error為空,不成功則返回相應(yīng)的錯(cuò)誤信息(可以使用error!.localizedDescription來(lái)打印查看錯(cuò)誤信息)。如果失敗的話(huà),alternateIconName屬性不變。這里注意:

如果當(dāng)期app使用的icon是備用的icon,那么這個(gè)屬性的值就是當(dāng)前icon的名字,這個(gè)名字是在Info.plist里面設(shè)置的名字,如果當(dāng)前app展示的是主要(primary)的icon,那么這個(gè)值為nil。

這里需要注意兩點(diǎn):

  1. 當(dāng)前設(shè)備的系統(tǒng)版本。這里的所有api都是10.3才能使用的。
  2. 當(dāng)前app是否支持備用icon。使用supportsAlertnateIcons屬性判斷。只有為true的使用才能去更改。
    API中還有一句話(huà)比較關(guān)鍵:
你必須在Info.plist里面使用CFBundleIcons聲明當(dāng)前app的primary和alternate icon。這里如果不了解可以往下看,先忽略。

具體的Info.plist里面的字段含義這里就不在一一說(shuō)明,詳情可了解這里

總之官方API上面我只找到了這么多。然而給我的感覺(jué)反倒一臉懵逼,完全搞不懂下面的Info.plist怎么設(shè)置。因此有了下面的序文。

個(gè)人理解

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

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

但是看一下Info.plist字典中的key,并沒(méi)有CFBundleDisplayName,替換后發(fā)現(xiàn),原來(lái)它就是Bundle display name。也就是說(shuō),Info.plist里面的Key在Xcode中顯示的并不是Key,而是Xcode name。如下圖:


Snip20170405_2.png
Snip20170405_2.png

這個(gè)是從官方API上截的圖,其實(shí)這些Key都有對(duì)應(yīng)的Xcode name,也就是在Xcodes里面我們能看到的key。其實(shí)也很簡(jiǎn)單,如果你把Info.plist使用源碼形式打開(kāi)(右擊—>Open as —>Source code),你就會(huì)發(fā)現(xiàn)這里寫(xiě)的key就是上面列出來(lái)的key。

先看看我在網(wǎng)上查資料設(shè)置的Info.plist:


Snip20170405_1.png
Snip20170405_1.png

這里的CFBundleIconFiles是備用icon的名字。下面的Primary Icon是默認(rèn)的icon。源代碼就是:


Snip20170406_2.png
Snip20170406_2.png

其中CFBundleIcons對(duì)應(yīng)的就是Icon files(iOS 5),CFBundleIconFiles就是Primary Icon。
先看一下CFBundleAlternateIcons。這個(gè)CFBundleAlternateIcons key所對(duì)應(yīng)的value在iOS里面是一個(gè)字典,例如:
Snip20170406_3.png
Snip20170406_3.png

每個(gè)字典的key是備用icon的名字,這個(gè)也是你傳入到

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

里面的iconName。其中的字典對(duì)應(yīng)值解釋如下:

Snip20170406_4.png
Snip20170406_4.png

CFBundleIconFiles:這個(gè)是一個(gè)String的數(shù)組,里面每個(gè)元素都是icon 的名字,你可以添加多個(gè)不同大小的icon來(lái)支持iPhone,iPad。
UIPrerenderedIcon:指定應(yīng)用程序的圖標(biāo)是否包含閃光效果(shine effect),如果icon已經(jīng)有這個(gè)效果,就把這個(gè)屬性設(shè)置為YES來(lái)防止系統(tǒng)再次添加相同效果。如果設(shè)置為NO(默認(rèn)值),iOS系統(tǒng)會(huì)自動(dòng)添加這個(gè)效果。然而,我并沒(méi)有測(cè)試出來(lái)這個(gè)效果!!
這里還要注意一下:Primary Icon的Item 0的name也可以不填寫(xiě),蘋(píng)果官方文檔也沒(méi)有具體說(shuō)名字這個(gè)要怎么去填寫(xiě),只是說(shuō)如果你想使用CFBundlePrimaryIcon鍵值定義的icon,直接使用將setAlternateIconName的參數(shù)alternateIconName寫(xiě)成nil就行。在屬性列表里面直接不填寫(xiě)就行(即把AppIcon60x60刪掉)

自己新建一個(gè)項(xiàng)目實(shí)現(xiàn)

自己實(shí)現(xiàn)需要注意兩個(gè)問(wèn)題:

  1. Info.plist怎么設(shè)置?
  2. 備用圖標(biāo)icon放到哪里?

首先來(lái)設(shè)置Info.plist。
按照蘋(píng)果官方的API說(shuō)法,那就先在Info.plist里面添加CFBundleIcons。但是查看了一下Key和Xcode name對(duì)應(yīng)的表格,CFBundleIcons對(duì)應(yīng)的是None,那就直接添加CFBundleIcons吧。點(diǎn)擊Information Property List后面的加號(hào),輸入CFBundleIcons,當(dāng)點(diǎn)擊Enter鍵的時(shí)候,你會(huì)驚奇發(fā)現(xiàn):你添加的CFBundleIcons變成了Icon files(iOS 5)字典。看看CFBundleIcons的官方API:


Snip20170406_6.png
Snip20170406_6.png

根據(jù)英文意思可以知道:該key包含了所有app使用的icons信息。新建的是這樣的:


Snip20170406_8.png
Snip20170406_8.png

可知默認(rèn)的包含了CFBundlePrimaryIcon和UINewsstandIcon。里面沒(méi)有CFBundleAlternateIcons,(我理解的應(yīng)該是蘋(píng)果不太想支持用戶(hù)添加備選icon,所以才沒(méi)有)。這里不過(guò)多介紹UINewsstandIcon了,它應(yīng)該是在NewStand上展示的吧,不太清楚,想了解可以看API,里面介紹了。
現(xiàn)在把NewStand Icon刪除,添加CFBundleAlternateIcons。添加后如圖所示:
Snip20170406_11.png
Snip20170406_11.png

但是看官方API對(duì)CFBundleAlternateIcon的介紹里面,并沒(méi)有UINewstandBindingType和UINewsstandBindingEdge,只有這個(gè):


Snip20170406_12.png
Snip20170406_12.png

也就是官網(wǎng)所說(shuō)的只有CFBundleIconFiles和UIPrerenderedIcon,那就刪了多余的那兩個(gè)UINewstandBindingType和UINewsstandBindingEdge。然后添加UIPrerenderedIcon:
Snip20170406_14.png
Snip20170406_14.png
。按照蘋(píng)果的說(shuō)法,把備用圖標(biāo)的名字放到Items0里面。我們先直接在左側(cè)導(dǎo)航中加入兩張圖片:newicon@2x.png 和newicon@3x.png,一個(gè)120 * 120,一個(gè)180 * 180。
但是看到上圖說(shuō)的設(shè)置,跑起來(lái)運(yùn)行代碼:
    @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("關(guān)閉彈出框")
        }
        alert.addAction(okAction)
        self.present(alert, animated: true, completion: nil)
    }

結(jié)果卻是:

The file doesn't exist

看了一下官方API對(duì)CFBundleAlternateIcons的介紹,里面有一句話(huà):

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

意思是這個(gè)CFBundleAlternateIcons中的字典的key是備用icon的名字,因此需要這樣修改:

Snip20170406_15.png
Snip20170406_15.png

也就是CFBundleAlternateIcons字典里面的key是備用icon的名字,然后以名字為key的字典里面又包含了CFBundleIconFiles和UIPrerenderedIcon。
這樣設(shè)置之后再次運(yùn)行你會(huì)發(fā)現(xiàn)成功更改了icon。
這樣就成功地改變了icon。
關(guān)于Primary Icon,直接不用設(shè)置Icon files就好了,如果你想設(shè)置為默認(rèn)的icon,就在setAlternateIconName里面?zhèn)魅雗il就好了。這個(gè)時(shí)候Info.plist源碼長(zhǎng)這樣:
Snip20170406_16.png
Snip20170406_16.png

在Property List里面,Primary Icon的Icon already includes gloss effects就是UIPrerenderedIcon,它的設(shè)置為false。(這里的光澤效果也是沒(méi)有測(cè)試出來(lái)有什么不一樣)
接下來(lái)看看備用icon是在哪里放著呢?
開(kāi)始的時(shí)候直接放到這里:
Snip20170406_17.png
Snip20170406_17.png

發(fā)現(xiàn)是OK的,可以正常顯示。
那么放到Assets.xcassets里面呢?放到Bundle里面呢?接下來(lái)將每個(gè)case都進(jìn)行測(cè)試:

  • 放到Assets.xcassets里面。新建一個(gè)普通的Image set,然后將圖片放到里面,效果如圖所示:


    Snip20170406_18.png
    Snip20170406_18.png

    經(jīng)過(guò)測(cè)試發(fā)現(xiàn),這樣放置是無(wú)法正常改變appicon的。但是運(yùn)行結(jié)果沒(méi)有任何錯(cuò)誤,而且系統(tǒng)提示里面加載的也是新的app icon:


    IMG_0022.PNG
    IMG_0022.PNG
  • 放到Assets.xcassets里面,并且新建的icon,如圖:


    Snip20170406_19.png
    Snip20170406_19.png

    運(yùn)行依然設(shè)置不成功。沒(méi)有錯(cuò)誤提示

  • 放到一個(gè)新建的Bundle里面。如圖所示:。


    Snip20170406_20.png
    Snip20170406_20.png

    運(yùn)行結(jié)果依然是沒(méi)有成功更改。沒(méi)有錯(cuò)誤提示。

所以經(jīng)過(guò)測(cè)試,發(fā)現(xiàn)只有放到導(dǎo)航里面的圖片才可以更改成功。在蘋(píng)果qa里面看到過(guò)一個(gè)場(chǎng)景,他們是直接在導(dǎo)航新建了一個(gè)文件夾,然后將圖片放到里面,然后使用。這里也推薦建立文件夾放入圖片,然后使用

另外,關(guān)于icon大小,可以參見(jiàn)這里

最后告訴大家一個(gè)不使用Asset來(lái)配置Icon的方法:直接在Info.plist下面這樣寫(xiě):


Snip20170406_22.png
Snip20170406_22.png

這個(gè)是通用的,可以直接設(shè)置iPhone和iPad的icon。其實(shí)這里也是想告訴大家:如何在CFBundleIconFiles里面去添加圖片數(shù)組:

 <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. 如果有什么疑問(wèn)歡迎留言提問(wèn)。或直接加群:206613455
    2.源碼地址:https://github.com/ScottZg/iOSChangeAppIcon
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評(píng)論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評(píng)論 3 418
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,463評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,009評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,778評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,218評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,436評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,795評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,993評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,229評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,659評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,917評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,687評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,990評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容