iOS 10.3 如何動(dòng)態(tài)更換App圖標(biāo)

原文鏈接:http://www.reibang.com/p/dd5144f8f021

動(dòng)態(tài)更換App圖標(biāo)這件事巨税,在用戶里總是存在需求的:有些用戶喜歡“美化”自己的手機(jī)吼蚁。至于用戶們喜歡美化到什么程度,這得看個(gè)人需求客峭。有的用戶想定制個(gè)性的App圖標(biāo),那么各大iPhone論壇里都有方法可以不越獄更改App圖標(biāo);有的用戶想讓App圖標(biāo)“動(dòng)”起來(lái)(如系統(tǒng)應(yīng)用時(shí)鐘)棚点,那么不越個(gè)獄還真不好辦。

不過(guò)今天我們想談?wù)勌O(píng)果官方對(duì)于動(dòng)態(tài)更換App圖標(biāo)的支持湾蔓。

本系列文章

iOS動(dòng)態(tài)更換App圖標(biāo)(一):基礎(chǔ)使用:http://daiyi.pro/2017/05/01/ChangeYourAppIcons1/
iOS動(dòng)態(tài)更換App圖標(biāo)(二):無(wú)彈框更換App圖標(biāo):http://daiyi.pro/2017/05/01/ChangeYourAppIcons2/
iOS動(dòng)態(tài)更換App圖標(biāo)(三):動(dòng)態(tài)下載App圖標(biāo)進(jìn)行更換
Demo演示

DynamicAppIconDemo1
Demo地址:https://github.com/maybeisyi/ChangeAppIconDemo

本篇文章對(duì)應(yīng)工程為:DynamicAppIcon(一)

Demo中可以看到瘫析,在不重新安裝App的情況下,可以實(shí)現(xiàn)更新App的圖標(biāo)默责。但是會(huì)彈出一個(gè)提示贬循,告知用戶當(dāng)前圖標(biāo)已更換,當(dāng)然下一篇文章將會(huì)突破這個(gè)“限制”桃序。

該功能應(yīng)用的場(chǎng)景

1杖虾、白天/夜間模式切換,在切換App主色調(diào)同時(shí)切換App圖標(biāo)媒熊。

2奇适、各類皮膚主題(淘寶就可換膚)坟比,附帶App圖標(biāo)一塊更換。

3滤愕、利用App圖標(biāo)表達(dá)某種特定功能温算,如Demo中的,提示當(dāng)前天氣间影。

4注竿、圖標(biāo)促銷提示,如淘寶京東特定節(jié)日:11.11魂贬、6.18巩割,提前更換App圖標(biāo)。

當(dāng)然該功能(API)當(dāng)前只支持iOS10.3以上的系統(tǒng)付燥,所以只能當(dāng)做一項(xiàng)附加功能來(lái)進(jìn)行使用宣谈。下面將詳細(xì)講解下如何使用代碼來(lái)實(shí)現(xiàn)此功能。

API與文檔

API方法

@interface UIApplication (UIAlternateApplicationIcons)
// 如果為NO键科,表示當(dāng)前進(jìn)程不支持替換圖標(biāo)
@property (readonly, nonatomic) BOOL supportsAlternateIcons NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));

// 傳入nil代表使用主圖標(biāo). 完成后的操作將會(huì)在任意的后臺(tái)隊(duì)列中異步執(zhí)行; 如果需要更改UI闻丑,請(qǐng)確保在主隊(duì)列中執(zhí)行.
- (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));

// 如果alternateIconName為nil,則代表當(dāng)前使用的是主圖標(biāo).
@property (nullable, readonly, nonatomic) NSString *alternateIconName NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
@end

總共3個(gè)方法勋颖,簡(jiǎn)潔明了嗦嗡,不過(guò)但看這3個(gè)API,我們并不清楚alternateIconName是如何與app圖標(biāo)掛鉤的饭玲,所以我們需要進(jìn)一步翻看文檔侥祭。

文檔

shift+command+0打開(kāi)文檔,依次查看3個(gè)API茄厘,翻譯如下:

supportsAlternateIcons

supportsAlternateIcons Document
(翻譯)只有系統(tǒng)允許改變你的app圖標(biāo)時(shí)該值才為YES矮冬。你需要在Info.plist文件中的CFBundleIcons這個(gè)鍵內(nèi)聲明可更換的app圖標(biāo)。

?

alternateIconName

alternateIconName Document
(翻譯)當(dāng)系統(tǒng)展示的是你更換后的app圖標(biāo)時(shí)次哈,該值即為圖標(biāo)名字(Info.plist中定義的圖標(biāo)名字)胎署。如果展示的是主圖標(biāo)時(shí),這個(gè)值為nil窑滞。

?

setAlternateIconName:completionHandler:

setAlternateIconName Document
(翻譯)alertnateIconName參數(shù):該參數(shù)為需要更換的app圖標(biāo)名字硝拧,是在你的Info.plist中的CFBundleAlertnateIcons鍵里定義的。如果你想顯示的是用CFBundlePrimaryIcon鍵所定義的主圖標(biāo)的話葛假,就傳入nil障陶。CFBundleAlertnateIcons與CFBundlePrimaryIcon鍵都是在CFBundleIcons里面定義的。

(翻譯)completionHandler參數(shù):該參數(shù)用來(lái)處理(更換)結(jié)果聊训。當(dāng)系統(tǒng)嘗試更改app的圖標(biāo)后抱究,會(huì)將結(jié)果數(shù)據(jù)通過(guò)該參數(shù)傳入并執(zhí)行(該執(zhí)行過(guò)程是在UIKit所提供的隊(duì)列執(zhí)行,并非主隊(duì)列)带斑。該執(zhí)行過(guò)程會(huì)攜帶一個(gè)參數(shù):error鼓寺。如果更換app圖標(biāo)成功勋拟,那么這個(gè)參數(shù)就是nil。如果更換過(guò)程中發(fā)生了錯(cuò)誤妈候,那么該對(duì)象會(huì)指明錯(cuò)誤信息敢靡,并且app的圖標(biāo)保持不變。

setAlternateIconName2 Document
(翻譯)使用該方法改變app圖標(biāo)為主圖標(biāo)或者可更換的圖標(biāo)苦银。只有在supportsAlternateIcons的返回值為YES時(shí)才能更換啸胧。

(翻譯)你必須在Info.plist文件的CFBundleIcons鍵里面聲明可以更換的app圖標(biāo)(主圖標(biāo)和可更換圖標(biāo))。如果需要獲取關(guān)于可更換圖標(biāo)的配置信息幔虏,請(qǐng)查閱 Information Property List Key Reference 里面有關(guān)CFBundleIcons的描述纺念。

?

文檔中反復(fù)提到了Info.plist文件與CFBundleIcons,這是Xcode6之前是用來(lái)配置App圖標(biāo)的老方法想括,后來(lái)有了更完備的Assets.scassets陷谱,配置App圖標(biāo)更簡(jiǎn)單與完善了。不過(guò)如今該方法再次被搬上臺(tái)面瑟蜈,在蘋(píng)果內(nèi)部一定也是歷經(jīng)多次“撕逼”后的結(jié)果烟逊,為何蘋(píng)果急于在10.3而不是11推出該API?為何蘋(píng)果不使用Assets.scassets配置可變更的App圖標(biāo)铺根?我們不得而知宪躯,不過(guò)相信蘋(píng)果后期會(huì)對(duì)該配置方法做優(yōu)化的。

可變更App圖標(biāo)的配置方法

官方配置文檔

CFBundleAlternateIcons1 Document
該配置文檔的內(nèi)容較多夷都,我們挑重點(diǎn)羅列下(忽略tvOS部分,下同):

Info.plist是個(gè)字典予颤,假設(shè)為NSDictionary *infoPlist囤官。

CFBundleIcons是Info.plist字典里的一個(gè)鍵@"CFBundleIcons"。

CFBundleIcons對(duì)應(yīng)的value是個(gè)字典蛤虐。
CFBundleIcons里面能夠包含的鍵有:CFBundlePrimaryIcon党饮、CFBundleAlternateIcons、UINewsstandIcon驳庭。
讓我們用代碼展示下這個(gè)繞口的結(jié)構(gòu):

NSDictionary *infoPlist;
infoPlist = @{
               @"CFBundleIcons" : @{
                                     @"CFBundlePrimaryIcon" : xxx,
                                     @"CFBundleAlternateIcons" : xxx,
                                     @"UINewsstandIcon" : xxx
                                   }
             };

CFBundleAlternateIcons2 Document
這是關(guān)于CFBundleAlternateIcons的配置文檔:

其中有一句話刑顺,不仔細(xì)思考很難明白:

In iOS, the value of the key is a dictionary. The key for each dictionary entry is the name of the alternate icon
翻譯:

該鍵對(duì)應(yīng)的值是字典,每個(gè)字典條目的鍵都是備用圖標(biāo)的名稱饲常。
從這句話中無(wú)法很快理清CFBundleAlternateIcons下層的數(shù)據(jù)結(jié)構(gòu)蹲堂。實(shí)際上這句話表達(dá)的意思是:

該鍵對(duì)應(yīng)的值是字典,這個(gè)字典里的每一個(gè)鍵對(duì)應(yīng)的又是一個(gè)個(gè)字典贝淤,而這些鍵都是備用圖標(biāo)的名稱柒竞。
讓我們把剩余的重點(diǎn)羅列下:

CFBundleAlternateIcons所對(duì)應(yīng)的value是個(gè)字典(iOS中),假設(shè)為NSDictionary * alertnateIconsDic播聪。
alertnateIconsDic的鍵朽基,都是備用圖標(biāo)的名字布隔,假設(shè)為@"newAppIcon"和@"newAppIcon2"。
@"newAppIcon"的value是個(gè)包含CFBundleIconFiles和UIPrerenderedIcon這兩個(gè)鍵的字典稼虎。
CFBundleIconFiles的value是字符串或者數(shù)組(數(shù)組內(nèi)容也為字符串)衅檀。字符串的內(nèi)容為各尺寸備用圖標(biāo)的名字。
UIPrerenderedIcon的value是BOOL值霎俩。這個(gè)鍵值所代表的作用在iOS7之后(含iOS7)已失效哀军,在iOS6中可渲染app圖標(biāo)為帶高亮效果。所以這個(gè)值目前我們可以不用關(guān)心茸苇。
讓我們用代碼展示下CFBundleAlternateIcons的value的結(jié)構(gòu):

@"CFBundleAlternateIcons" : @{
                               @"newAppIcon" : @{
                                                 @"CFBundleIconFiles" : @[
                                                                            @"newAppIcon"
                                                                         ],
                                                 @"UIPrerenderedIcon" : NO
                                                },
                               @"newAppIcon2" : @{
                                                 @"CFBundleIconFiles" : @[
                                                                            @"newAppIcon2"
                                                                         ],
                                                 @"UIPrerenderedIcon" : NO
                                                 }
                             }

實(shí)際配置文件(Info.plist)

對(duì)照著上述的配置文檔排苍,我們實(shí)際配置完的Info.plist是這樣子的:

Info.plist1
當(dāng)然也要拖入對(duì)應(yīng)的App圖標(biāo):

各種天氣App圖標(biāo)
不過(guò)這里我們好像還少配置了App主圖標(biāo),也就是正常情況下我們的圖標(biāo)学密。按照文檔所說(shuō)淘衙,我們需要在CFBundleIcons里面配置CFBundlePrimaryIcon這個(gè)主圖標(biāo)對(duì)應(yīng)的內(nèi)容,但是實(shí)際上腻暮,我們還是按照老方法彤守,在Assets.xcassets中配置AppIcon,對(duì)應(yīng)尺寸填上對(duì)應(yīng)圖片即可哭靖。為什么這樣子就可以配置主圖標(biāo)呢具垫?讓我們來(lái)看看某知名電商的ipa(在AppStore上下載的包)內(nèi)的Info.plist(位于Payload/XXXXXX/Info.plist):

知名電商的Info.plist
當(dāng)然你也可以在你自己App打出的包內(nèi)進(jìn)行查看,系統(tǒng)其實(shí)是會(huì)將Assets.xcassets中配置的AppIcon轉(zhuǎn)化為Info.plist中的CFBundlePrimaryIcon试幽。所以我們主圖標(biāo)的配置方式還是與原先一樣筝蚕。

其他注意事項(xiàng):

文件擴(kuò)展名,如@2x,@3x铺坞,要么統(tǒng)一不寫(xiě)起宽,那么系統(tǒng)會(huì)自動(dòng)尋找合適的尺寸。要寫(xiě)就需要把每張icon的擴(kuò)展名寫(xiě)上济榨,和上圖的格式一樣坯沪,在本系列文章的Demo中也有一個(gè)單獨(dú)的Demo示例如何添加多尺寸icon。
iPad版本如果需要有更換的圖標(biāo)擒滑,需要在CFBundleIcons?ipad同樣設(shè)置一次腐晾。
更換圖標(biāo)后,如何驗(yàn)證iPhone上使用了多尺寸的圖標(biāo)丐一?

所有尺寸圖標(biāo)
打開(kāi)DynamicAppIcon(帶尺寸)這個(gè)Demo藻糖。該Demo中,我們?cè)诟鱾€(gè)尺寸的圖標(biāo)右上角打個(gè)”標(biāo)記“库车,然后使用上文介紹的setAlternateIconName:completionHandler:進(jìn)行圖標(biāo)更換颖御。更換圖標(biāo)的同時(shí),我們?cè)僮鲆患拢?/p>

// 測(cè)試推送上是否使用了20尺寸的圖標(biāo)
UILocalNotification *noti = [[UILocalNotification alloc] init];
noti.fireDate = [NSDate dateWithTimeIntervalSinceNow:5];
noti.alertBody = @"我們看看推送上面的App圖標(biāo)";
[[UIApplication sharedApplication] scheduleLocalNotification:noti];
這里我們發(fā)送了一個(gè)本地通知,一會(huì)我們就能看到通知上顯示的是什么圖標(biāo)了:

本地推送圖標(biāo)對(duì)比
再讓我們?nèi)ettings里面觀察下App圖標(biāo):

設(shè)置界面圖標(biāo)對(duì)比
看到圖標(biāo)的區(qū)別潘拱,也就說(shuō)明了我們?cè)贗nfo.plist里面設(shè)置的多尺寸圖標(biāo)生效了:

多尺寸Info.Pilst
下一篇

在這篇文章里疹鳄,你能看到App圖標(biāo)在運(yùn)行時(shí)被更換了,但是更換的時(shí)候會(huì)給出一個(gè)“擾人”的彈框芦岂,該彈框是蘋(píng)果爸爸默認(rèn)加上去的瘪弓,下一篇就是告訴各位,如何反抗爸爸:去除更換App圖標(biāo)時(shí)的彈框禽最。
iOS動(dòng)態(tài)更換App圖標(biāo)(二):無(wú)彈框更換App圖標(biāo)(簡(jiǎn)書(shū)地址):http://www.reibang.com/p/dd5144f8f021

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腺怯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子川无,更是在濱河造成了極大的恐慌呛占,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件懦趋,死亡現(xiàn)場(chǎng)離奇詭異晾虑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)仅叫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門帜篇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人诫咱,你說(shuō)我怎么就攤上這事笙隙。” “怎么了坎缭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵竟痰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我掏呼,道長(zhǎng)坏快,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任哄尔,我火速辦了婚禮假消,結(jié)果婚禮上柠并,老公的妹妹穿的比我還像新娘岭接。我一直安慰自己,他們只是感情好臼予,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布鸣戴。 她就那樣靜靜地躺著,像睡著了一般粘拾。 火紅的嫁衣襯著肌膚如雪窄锅。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音入偷,去河邊找鬼追驴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛疏之,可吹牛的內(nèi)容都是我干的殿雪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼锋爪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼丙曙!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起其骄,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤亏镰,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后拯爽,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體索抓,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年某抓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纸兔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡否副,死狀恐怖汉矿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情备禀,我是刑警寧澤洲拇,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站曲尸,受9級(jí)特大地震影響赋续,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜另患,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一纽乱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧昆箕,春花似錦鸦列、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至纤泵,卻和暖如春骆姐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工玻褪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留卵佛,地道東北人瓤球。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓倘是,卻偏偏與公主長(zhǎng)得像惨驶,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子庸诱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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