對于矢量圖的調(diào)研, 最開始是始于對其占用iOS App的空間的好奇。筆者好奇一個(gè)問題: 利用矢量圖能不能幫助iOS App減少整體空間?
iOS其實(shí)在很早的時(shí)候就已經(jīng)支持矢量圖的應(yīng)用(XCode 6時(shí)代開始支持), 只不過因?yàn)榇蟛糠珠_發(fā)者沿用了以前@1x凡辱、@2x戒职、@3x格式圖的習(xí)慣, 并沒有一個(gè)地方專門普及使用矢量圖。當(dāng)然, 還有另外一個(gè)原因就是iOS對復(fù)雜的矢量圖支持的不是很好透乾。
本文并沒有特別深入的技術(shù)點(diǎn), 僅僅只是筆者做的幾個(gè)實(shí)驗(yàn)的總結(jié)和矢量圖基礎(chǔ)使用的教程普及~
矢量圖和iOS
關(guān)于矢量圖在iOS中的使用早在15年2月就有一篇博文介紹了它的使用 - iOS使用矢量圖的總結(jié)洪燥。筆者按照它的用法操作了一遍, 基本大同小異~ 針對該文章沒有涉及到的一些細(xì)節(jié), 筆者進(jìn)行一定程度的補(bǔ)充磕秤。
iOS中矢量圖的使用方法
筆者為了做一下簡單的矢量圖實(shí)驗(yàn), 使用Sketch隨意拖了一個(gè)星星出來并導(dǎo)出一個(gè)PDF。(實(shí)際上UI繪制矢量圖的工具有很多很多, 這里不贅述捧韵。如果讀者懶得自己去導(dǎo)出, 可以直接挪用)
XCode支持矢量圖一定要放置在xcasset文件中才能夠生效, 操作步驟如下:
- 拖拽提前制作的PDF進(jìn)入
XXX.xcassets
中市咆。 - 選擇
Image Set
下的參數(shù)選項(xiàng)Scale Factors
為Single Vector
或Vector With Overrides
- 如果圖形不在框框中, 拖入框框中(XCode某些版本不能自動(dòng)對號入座)
Vector With Overrides
是Single Vector
的增強(qiáng), 可以在放置完矢量圖之后繼續(xù)放置@1x、@2x和@3x的png格式的圖片再来。放置的png會(huì)優(yōu)先覆蓋矢量圖, 未放置對應(yīng)倍率圖片的設(shè)備才會(huì)使用矢量圖對應(yīng)生成的圖片蒙兰。
矢量圖在iOS中的應(yīng)用原理
iOS對矢量圖的支持其實(shí)只是一種方便開發(fā)者的選擇, 本質(zhì)上在XCode編譯的階段矢量圖會(huì)自動(dòng)生成對應(yīng)Target的@1x,@2x和@3x的png格式圖像芒篷。在iOS實(shí)際運(yùn)行中使用的圖片實(shí)際上已經(jīng)是png格式的圖片了~
通俗的理解 - 放置在xcassets里的矢量圖會(huì)自動(dòng)根據(jù)設(shè)備編譯成對應(yīng)尺寸的圖片, 如果是Generic iOS Device
則會(huì)自動(dòng)生成全尺寸的同名圖片搜变。
PS: 自動(dòng)生成的@1x圖會(huì)和矢量圖的原始尺寸保持一致。
下圖為利用ThemeEngine打開的基于Generic iOS Device
編譯出來的Assets.car文件
矢量圖能否減少空間
回歸到最初的問題, 到底使用矢量圖能不能幫助iOS App減少空間呢?
筆者用簡單粗暴的實(shí)驗(yàn)來對比說明, 步驟如下:
- 使用pdf原始文件編譯生成通用IPA
- 從生成的IPA文件中提取Asset.car文件
- 利用iOS Image Extractor提取Asset.car文件
- 將提取出來的@1x针炉、@2x挠他、@3x放置回工程, 并刪除原始pdf中重新編譯
- 對比步驟1生成的car文件和步驟4生成的car文件大小
- 步驟一編譯car大小(僅PDF) - 115KB
- 步驟四編譯car大小(僅3張圖) - 86KB
- 測試PDF尺寸 - 20KB
在iOS8.3以下, 相同壓縮比例的條件下, 矢量圖是無法幫助App減少空間。但是在iOS8.3以上, 利用xcassets可以避免多余的資源圖片下載, 只下載對應(yīng)的倍率的圖片篡帕。因此, 嚴(yán)格意義下, 利用矢量圖并不能幫助App節(jié)省空間殖侵。
其實(shí)筆者使用的簡單粗暴的方式在蘋果新的瘦身機(jī)制下是不成立的, 因?yàn)榫幾g生成的最終包不一定就是設(shè)備最終安裝的包。引用官方文檔App Thinning中Slicing章節(jié)中的一段話:
In Xcode, specify target devices and provide multiple resolutions of images in the asset catalog.
You must use the asset catalog in order for resources to be sliced.
筆者未能完全參透這句話的意思, 只知道xcasset會(huì)根據(jù)不同的設(shè)備會(huì)有不同的解決方案, 但是不知道粒度會(huì)達(dá)到什么樣的程度镰烧。筆者嘗試過針對不同的模擬器編譯, 只會(huì)生成對應(yīng)的倍率圖, 但是上傳給App Store是通用格式的, 難道下載的過程中進(jìn)行了一定的處理? 這個(gè)就需要一臺越獄設(shè)備去驗(yàn)證了, 就靠各位讀者大大了~
PS: 對iOS如何控制多余資源圖片下載感興趣的童鞋們, 可以找一臺越獄設(shè)備, 將iOS 8.3以上的App給提取出來分析分析哈~ 記得分享哇~ \(o)/
題外探究之提取原理
筆者在對比大小的時(shí)候使用的iOS Image Extrator拢军。 在使用過程中, 筆者對該工具的提取原理產(chǎn)生了那么一點(diǎn)點(diǎn)的好奇。筆者好奇xcasset的格式應(yīng)該是封閉不開放的, 該工具是怎么從Asset.car中提取圖片的, 難道該工具破解了Asset.car的格式?
既然iOS Image Extrator是開源的, 那么筆者就有必要去看一看究竟了~ iOS Image Extrator其實(shí)是基于開源庫iOS Asset Extrator開發(fā)實(shí)現(xiàn)的, 核心提取的功能是在iOS Asset Extrator庫下提取的, 筆者通過閱讀其源碼, 找到兩個(gè)核心方法exportToDirectory:和exportThemeRendition:
通過閱讀這兩個(gè)方法的源代碼可以了解到這個(gè)庫的基本實(shí)現(xiàn)怔鳖。exportToDirectory:方法有該庫核心的提取圖片的所有邏輯代碼朴沿。而exportThemeRendition:可以看出該庫支持的所有格式, 并且通過蘋果內(nèi)置的各個(gè)格式的Rendition
類提取導(dǎo)出。
iOS Asset Extrator庫本質(zhì)上調(diào)用的是蘋果的私有API败砂。在該系列API中, CUICommonAssetStorage
負(fù)責(zé)存儲Asset資源的關(guān)鍵key, CUICatalog
是承載了具體資源圖片信息的登記目錄赌渣。
<font color="red">回歸主題, 開源庫底層既然是蘋果API, 那么就基本是一個(gè)黑盒子了。筆者既不能從暴露的API中分析出car的格式, 又不能判斷iOS設(shè)備是否在執(zhí)行中解壓, 只好放棄</font>~
總結(jié)
矢量圖嚴(yán)格意義上并不能幫助減少App的空間, 但是卻使用起來非常的方便, 建議使用昌犹。iOS本質(zhì)上并不支持矢量圖, 但是在編譯階段會(huì)將矢量圖轉(zhuǎn)化成目標(biāo)設(shè)備對應(yīng)的尺寸圖, 同時(shí)會(huì)利用xcassets的特性在iOS8.3以上設(shè)備下支持部分資源下載, 帶到包瘦身的效果坚芜。每次都要讓UI給多個(gè)尺寸的圖, 肯定沒有給一張方便吧? 當(dāng)然, 前提是UI的童鞋是基于矢量圖工具制作的圖片的前提下~