您好,登錄后才能下訂單哦!
戴維營教育原創文章,轉載請注明出處。我們的夢想是做最好的iOS開發培訓!
與iOS 9和watchOS 2一起,蘋果引入了一套新的內容分發API,以便節約設備空間,這就是按需加載資源。通過使用按需加載資源,我們可以將特定的應用程序資源托管在蘋果的服務器上,然后在需要的時候進行加載。在這個教程中,我將通過開發一個圖片查看應用介紹一下按需加載資源的基本用法。
這個教程需要使用Xcode 7+并且熟悉iOS開發。可以到Github上下載初始項目。
iOS 9和watchOS 2引入按需加載資源的主要目的是減少單個應用程序所占的空間。另外一個好處是我們的應用程序能夠更快的被用戶下載下來并且啟動。
通過使用Xcode中的asset pack所唯一分配的tags來獲取按需加載資源。這些資源包可用包含任何asset中的內容(圖片、SpriteKit紋理、數據等),甚至其它文件如OpenGL和Metal的著色器、SpriteKit和SceneKit的場景文件以及粒子系統。
當我們將應用提交到App Store時,這些資源也會被上傳和托管,以便需要的時候下載。程序運行的時候,只要使用在Xcode中設置的tag就可以非常方便的獲取到資源。
使用按需加載資源最多的兩個方面是app bundle,包含可執行代碼和重要的資源,例如UI圖標和asset packs。
在Xcode中可以將這些資源分為三個主要的類別:
初始安裝: 第一次運行需要的內容,過后可以刪除。一般可以包含游戲的開始幾關,當游戲進度足夠遠的時候就可以刪除了。
預取: 這個類別的內容在安裝完應用后就需要立即下載。這個類型的數據應該應用在那些非必需的資源上,但是如果安裝了可以獲取更好的用戶體驗。比如游戲的新手教程。
按需加載: 在程序運行過程中下載,不會影響程序的運行。這是我們使用最多的按需加載類型。
支持按需加載資源的應用程序需要遵循以下限制:
iOS應用程序不能超過2GB
初始安裝的tag不能超過2GB
預取tag不能超過2GB
正在使用的資源不能超過2GB。這一點只有當應用正在運行并且使用了按需加載資源的時候才起作用。
每個asset pack不能給你超過512MB。如果超過了這個限制,Xcode將給出警告并且允許我們繼續測試和開發程序,但是提交到App Store時會失敗。
蘋果為每個應用提供最多20GB的空間進行托管,這也是每個程序一次最多可以下載的資源數量。當然,應用程序一次最多只能使用2GB的資源。
注意20GB的限制是所有應用程序分片的總和,而是總共20GB。那什么是應用程序分片呢?應用程序分片是iOS 9引入的,用于降低應用大小的一個特性。當應用被安裝后,它只會查找與設備對應的資源。例如,當資源被正確使用的時候,iPhone 6 Plus或6s Plus只會加載3x的圖標,而不會下載1x和2x的。所以整個按需加載資源的總的大小是20GB,包含我們上傳到App Store服務器的所有設備類型需要的資源總和。除此以外其它限制條件都是針對特定的設備類型單獨設置的。
已經下載的按需加載資源只有當設備空間不夠時才會被清理。當空間不夠時,按需加載資源系統會查看設備上的所有應用,并且根據資源的最后使用時間決定刪除哪個。如果應用程序正在運行,它擁有的資源永遠都不會被清理。
使用Xcode打開啟動項目并且在模擬器中運行程序。它包含一組圖片,由三種顏色(紅、綠、藍)和四種形狀(圓、正方形、星形和六邊形)組合而成。當程序運行的時候,選擇Colors > Red,我們可以看到一個紅色的圓。
我們在程序中設置7個asset pack,每個包含一種顏色和一個形狀。按需請求資源的另外一個特性是每個資源可以設置多個Tag。比如紅色的圓可以同時是Red和Circle包的一部分。
按需請求資源API對同一個資源不會下載兩次。換句話說,就是如果已經下載Red包,那么在下載Circle包的時候,不會再次下載紅色圓形這個圖片。
在Xcode中,打開Assets.xcassets。我們可以看到12張圖片。
下一步,選擇藍色方塊圖片集,并且打開Attributes Inspector。
在Attributes Inspector中包含一個新的On Demand Resource Tags組,可以用來設置資源的標簽(Tag)。我們給藍色方塊設置Blue和Square標簽。
設置好資源的Tag后,打開Xcode左側的Project Navigator,點擊Resource Tags標簽并且選擇Prefetched進行過濾。
我們可以非常方便的看到每個資源包的大小以及里面所包含的內容。Prefetched中顯示每個類別中的資源,并且允許在不同的類別中進行移動:
初始安裝
預取
按需下載
這正是我之前所提到的三個類別。Prefetched Tag Order組中的資源在顯示的時候自動開始下載。
設置好了所有的圖片資源后,就可以開始訪問這些內容了。
我們使用NSBundleResourceRequest
獲取App Store服務器托管的資源包。使用需要獲取的資源的Tag創建request對象。它會告訴系統我們所需要使用的資源包是哪個。而釋放這些對象則告訴系統我們不再需要這些資源包了。一定要注意不能超過2GB的資源限制。
在項目中,打開DetailViewController.swift并且在DetailViewController
中添加一下屬性。
var request: NSBundleResourceRequest!
下一步,替換viewDidAppear(_:)
方法。
override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) request = NSBundleResourceRequest(tags: [tagToLoad]) request.beginAccessingResourcesWithCompletionHandler { (error: NSError?) -> Void in // Called on background thread if error == nil { NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in self.displayImages() }) } }}
剛才的代碼中我們用Tag初始化了一個request
對象。tagToLoad
屬性是在前一個頁面設置的,表示我們要顯示的內容是什么。
下一步,我們通過調用beginAccessingResourcesWithCompletionHandler(_:)
開始下載特定Tag標明的資源包。這個方法自動訪問Tag對應的所有資源,并且開始下載。一旦獲取到資源后,其它代碼一切照舊。
注意,如果我們只希望訪問已經下載的資源,而不想繼續加重內容。可以調用conditionallyBeginAccessingResourcesWithCompletionHandler(_:)
。
需要提醒的是,上面方法的執行完后,handler是在子線程中執行的,因此需要切換到主線程再更新UI。
我們已經成功的在程序里使用了按需加載資源,簡單吧!
Xcode 7的有一個重要的調試特性就是能夠查看當前下載了那些資源包。點開Debug Navigator并且選擇Disk就可以看到了。
我們可以改變一下資源的下載優先級,這樣有些內容就會總是立馬下載。同時還可以改變資源的保存優先級,比如Hexagon和Star會在Circle和Square之前清理。將代碼改成一下樣子:
override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) request = NSBundleResourceRequest(tags: [tagToLoad]) request.loadingPriority = NSBundleResourceRequestLoadingPriorityUrgent NSBundle.mainBundle().setPreservationPriority(1.0, forTags: ["Circle", "Square"]) NSBundle.mainBundle().setPreservationPriority(0.5, forTags: ["Hexagon", "Star"]) request.beginAccessingResourcesWithCompletionHandler { (error: NSError?) -> Void in // Called on background thread if error == nil { NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in self.displayImages() }) } }}
初始化request對象后,我們可以設置loadingPriority
屬性為NSBundleResourceRequestLoadingPriorityUrgent
。當然,也可以設置0-1之間的任意值來表明加載優先級。
這個常量自動設置請求為最高加載優先級,但是這取決于當前的CPU活動情況。在某些情況下,如果CPU任務繁忙,資源的下載可能會被推遲。
下一步我們通過mainBundle的setPreservationPriority(_:forTags:)
設置四個形狀的保存優先級。這時我們就可以確認,一旦按需加載系統需要清理一些資源的時候,就會先刪除Hexagon和Star。
現在我們知道了如何在iOS應用里使用按需加載資源。下面我想給大家介紹一些需要注意的地方。
為了減少資源的加載時間,使得每個資源更容易訪問,應該讓每個資源包保持盡可能的小。這樣就不會導致被過度清理。
例如,系統本身需要釋放50MB的空間,但是如果最合適被刪除的包是400MB,這樣就會導致350MB的內容被不必要的刪除。這就意味著下次需要的時候又要多下350MB。建議每個資源包的大小應該接近64MB。
如果你的應用有一個非常容易預見的用戶操作過程,最好是提前就開始下載資源。這樣可以提高用戶體驗,而不需要他們等待太久。
游戲是一個非常常見的場景。如果一個玩家已經完成了前5關,我們最好在他玩第6關的時候,開始下載第7關。
如果不在需要訪問某個資源包,確保釋放NSBundleResourceRequest
對象或者調用endAccessingResources
方法。
這樣不僅可以防止我們的應用達到2GB的限制,而且可以幫助系統知道什么時候需要訪問這些資源,從而更好的決定如何刪除資源來獲取更多空間。
在我的另外一篇關于tvOS的博客提到tvOS的應用限制。比如最大程序大小為200MB,因此更應該使用按需方法資源。
tvOS和iOS的按需訪問資源的其它限制是一樣的,只是要注意tvOS僅使用1x的圖片,因此并不會因為應用程序分片的存在而減少空間。
iOS 9和tvOS上的按需加載資源是用來減少程序大小和提供更好用戶體驗的一個非常重要的方法。它非常容易使用和設置,但是要注意它的加載時間和數據清理所帶來的一些問題。
戴維營學院(高級開發視頻): http://v.diveinedu.com
潛心俱樂部(iOS面試必備): http://divein.club
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。