改變iOS app的icon(iOS10.3)

来源:http://www.cnblogs.com/zhanggui/archive/2017/04/06/6674858.html
-Advertisement-
Play Games

iOS10.3新增了可以讓開發者去更改app的icon,接下來看看怎麼更改。 ...


改變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裡面。我們先直接在左側導航中加入兩張圖片:[email protected] [email protected],一個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

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上一篇講到局部變數可以修改全局變數,那麼反過來是否可以由外而內的拿到函數內的數據呢?答案是可以的下麵就介紹兩種方法。 1、通過聲明全局變數的方式: 執行結果 要由外而內的進行操作需要先聲明一個全局變數,然後通過給全局變數賦值的形式進行。 2、局部變數的調用 由外而內的進行操作也可以通過局部變數的調用 ...
  • 最近看見別人問的問題,點擊雷達圖的拐點,獲取點擊數據的問題,直接上代碼。 echarts配置問題:https://www.douban.com/note/509404582/ 還有一個就是給雷達圖的文字綁定點擊事件,上代碼。api地址:http://echarts.baidu.com/tutoria ...
  • 一個項目開發完,開發除了做好功能測試以外,還要做些性能方面的測試,除了依賴一些工具去檢查,有一些常用的檢查也是必要的: 1.弱網情況下測試網頁載入速度,以及是否有良好的loading體驗 2.js、css、image這些是否都懶載入 3.js和css是否都儘量合併壓縮到一個文件 4.icon是否都盡 ...
  • 在預解析原理(一)中我們簡單介紹了一下JS的解析過程,這篇文章會對這個過程進行深入的分析。 在這個過程中首先需要明白三個概念: 1、全局作用域:也就是全局變數聲明在函數之外的變數預設作用整個工程; 2、局部作用域:聲明在函數體中的變數,並且只能在當前函數體內訪問,如:function(){var a ...
  • FIS3常用配置: ...
  • 一、作用域概念、預解析規則、表達式 1、作用域概念 什麼是作用域:簡單說就是作用的範圍,指的是函數在哪些範圍內可以用,而在其他部分就不可以使用,如果需要使用就需要重新定義。 作用域的作用是什麼:用來執行讀或者寫的操作。 2、預解析規則 script:自上而下進行解析, 函數:由里到外進行解析。 但是 ...
  • 背景 項目使用 , 對應Ext JS4.2版本。 結果 2017/3/31 號的時候偶然間點日曆選擇控制項選擇2月,10月等月份突然就跳到3月份,9月份之類。 就是無法選擇, 選擇谷歌以後發現有同樣的問題, 然後各種嘗試, 重寫了預設屬性,如下代碼後解決。 現記錄。 改動的部分就是 這一句, 設置為當 ...
  • vue-cli 用vue-cli來搭建vue項目 第一步:全局安裝vue-cli 第二步:初始化一個項目 第三步:把文件切換到初始化的項目中 第四步:安裝依賴 當然也可以用淘寶鏡像cnpm來安裝,這樣快很多 第五步:運行 完成一個初始化vue項目 webpack 要開始一個vue項目, 那也必須要了 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...