This is the third day of my participation in the August More text Challenge. For details, see:August is more challenging
preface
If you’re not sure what ODR: On-demand Resources is, check out Apple’s official resource reduction plan, ODR (1) : First Look
Now that you know what the ODR can do, take a shot at your own project. I use my personal project dream account here, and since there are multiple sets of skins that can be replaced in the project, there are many sets of ICONS saved, which are suitable for optimization using the ODR.
About THE ODR in addition to the official document, also did not find a lot of practical information, here combined with the document, hand touch hand and everyone to practice a wave of it.
Let’s start with a seller show
Before using the ODR
After using the ODR!
The size of the download on TestFlight has not yet been approved for release on 2.7.1 as of this writing, but it will not differ much from the actual download.
Enable the ODR
It’s on by default since iOS9
Create a label
Tags are used to identify and manage a set of ODRs. Assigning one or more tags to a resource in a project identifies it as an ODR. At run time, access to all Odrs works with labels rather than individual resources.
You can see the entry point for adding a tag in Target’s Resource tags, where you can select the resources in the project to add to the tag.
Resource organization before the project:
In order to facilitate label management, we split the resource bundle:
2.1 Add a tag to Assets
Add Assets to Tag:
2.2 Confirm that the resource label is set successfully
Open the resource bundle to view the resource information, and you can see the matching resource label here. (Multiple tags can be set for a resource)
When building a project, Xcode checks all tagged projects in the project and generates resource bundles for use by the operating system.
2.3 Quickly Adding a Label to a Resource
You can also quickly add an existing label to a single resource or quickly create a label by entering Lenovo directly.
Three, label classification
By switching to Prefetched, we see three categories:
The default category for labels created is to download the ODR on demand only. Labels can be dragged between categories.
- Initial install tags.
- Resources are downloaded at the same time as applications. The size of the resource is included in the total size of the application in the app store. When there’s nothing
NSBundleResourceRequest
It may be cleared when accessed.
- Resources are downloaded at the same time as applications. The size of the resource is included in the total size of the application in the app store. When there’s nothing
- Prefetch tag order.
- After the application is installed, resources are downloaded. Download in label order.
- Dowloaded only on demand.
- Load on demand. These tags are downloaded when the request is applied.
When the operating system downloads a label, it only downloads resources that are not available on the device.
3.1 Setting label Categories
Setting up a label category is as simple as dragging from the default ODR list to the corresponding category.
Here I set the default resource for both skins to Initial install
Four, size limit
After shearing is applied, the total size of resources in the label cannot exceed 512 MB. The total size of on-demand resources stored in the app store must not exceed 20 GB.
The ideal size of the label is not greater than 64 MB. This size provides a good balance between download speed and local storage, so that it can be cleared if the device’s local storage is low.
- Slicing.
- Check tags (✓) indicate that the size reflects the clipping size of the application.
- App bundle.
- Size of the clipped application package downloaded to the device.
- Asset packs.
- Asset packages are generated by Xcode.
- Initial install tags.
- The mark is the total cut size of the mark for the initial installation.
- Initial install and prefetched tags.
- Marked as
Initial install
和Prefetch tag
The total size of the resource after shearing
- Marked as
- In use on-demand resources.
- One row at most is available
ODR
The shear size of.
- One row at most is available
- Hosted on-demand resources.
- all
ODR
Size, uncut size.
- all
5. Manage ODR
After configuring the label, run the project directly. You can see that none of the ODR resources have been downloaded.
5.1 Determining the ODR update time
Here’s a description of the dream account skin logic to help determine when to update the ODR:
- Skin is divided into two modes: Normal mode and Dark mode.
- That is, the user can set the skin for the two modes, and the dark mode switch can be switched seamlessly
- Setting the skin will reset the root controller
- Here is a node where the ODR needs to be updated
- Another node to check for updates is when the application starts
- Check the current two skins and prepare resources for related labels
5.1 NSBundleResourceRequest Requests resources
A tag can be managed by multiple instances. Here are three important apis.
Initialize the
- Tags: Collections of tags
- Bundle: Usually main
public init(tags: Set<String>, bundle: Bundle)
Copy the code
Check the status
Check whether all the resources for the requested label have been saved in the device.
open func conditionallyBeginAccessingResources(completionHandler: @escaping (Bool) - >Void)
Copy the code
Start requesting resources
Request a tag resource that is not local.
open func beginAccessingResources(completionHandler: @escaping (Error?). ->Void)
Copy the code
Vi. Transformation of “Dream account book”
6.1 packaging OdrTool
protocol OdrTagProtocol {
var tagName: String { get}}struct OdrTool {
static func requestODR(of tags: OdrTagProtocol. .in bundle: Bundle = Bundle.main) {
var tagsSet: Set<String> = []
tags.forEach { tagsSet.insert($0.tagName) }
let request = NSBundleResourceRequest(tags: tagsSet, bundle: bundle)
request.conditionallyBeginAccessingResources { hasCache in
if hasCache = = false {
// These resources are not all local
request.beginAccessingResources { error in
if let _ = error {
// Download failed
}
else {
// Download succeeded}}}else {
// These resources are already local}}}}Copy the code
6.2 Expand Odr for AppearanceStyle skin system
AppearanceStyle is the core of the entire skin dressing system, and the body is an enumeration.
- In this case, make the original skin match the name of your label.
- And then add a
reloadOdr
Method to update the current two skinsODR
extension AppearanceStyle: OdrTagProtocol {
static func reloadOdr(a) {
OdrTool.requestODR(of: currentLightStyle, currentDarkStyle)
}
var tagName: String {
switch self {
case .Charge.ChargeMain:
return "Charge"
case .ChargeLight:
return "ChargeLight"
case .Eternal.Hachimitsu:
return "Eternal"
case .Spark:
return "Sakura"
case .SparkMain:
return "Spark"
case .NYXL:
return "NYXL"
case .Justice.Dream.Phoenix:
return "Justice"
case .Kiwi:
return "Kiwi"
case .Banshee:
return "Banshee"
case .Punk:
return "Punk"}}}Copy the code
6.3 Updating Odr Resources on Appropriate Nodes
Node 1: The application starts
AppearanceStyle.reloadOdr()
Copy the code
Node 2: Set the skin
static func reloadApp(a) {
guard let tabVC = UIStoryboard(name: "Home", bundle: nil).instantiateInitialViewController() else {
return
}
UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.rootViewController = tabVC
reloadOdr()
}
Copy the code
6.4 Run the project and check the effect
Xcode shows that the resources for the two skins I set have been downloaded.
But open the App and it’s still blank?
6.5 Troubleshooting
As previously understood, ODR resources are cleaned up if they are not used by any NSBundleResourceRequest. The wrapper above does not hold an NSBundle of properties. Make some changes to the code.
OdrTool
struct OdrTool {
static func requestODR(of tags: OdrTagProtocol. .in bundle: Bundle = Bundle.main) -> NSBundleResourceRequest {
.
let request = NSBundleResourceRequest(tags: tagsSet, bundle: bundle)
.
// Throw NSBundleResourceRequest
return request
}
}
Copy the code
AppearanceStyle
extension AppearanceStyle: OdrTagProtocol {
// Add a static variable to save
static var odrRequest: NSBundleResourceRequest?
static func reloadOdr(a) {
odrRequest = OdrTool.requestODR(of: currentLightStyle, currentDarkStyle)
}
var tagName: String {
switch self {
.}}}Copy the code
6.6 Checking the Modification Effect
Perfect ~ also tested the function of switching skin is no problem
If you look at Xcode, the status of the tags is different. The two tags that are In use are now In use.
6.7 Do I Need to Change the Resource Usage?
Don’t have to
Seven,
The experience is still very smooth, feel access cost is not high. I am quite familiar with my personal project, and the skin peeling system is well sealed 😜 also brings great convenience to access ODR. And my single skin resources only about 2M download is also very fast.
It might not be as simple as what I’m dealing with if it’s a larger resource load. And there are a lot of Settings that I don’t use in NSBundleResourceRequest, so if you want to know more about it, you can read the official documentation, so I’ll just throw a brick here 🧱.
And any choice of optimization program should be combined with the actual project, can copy the program is not exist. Apple’s ODR is good, but I feel that it has not entered the broad view of iOSer, it is a pity, if it feels right for your project can really use oh ~
👋 Bye ~
- Wechat: RyukieW
- 📦 Technical article archive
- 🐙 making
My personal project | Mine Elic endless sky ladder | Dream of books |
---|---|---|
type | The game | financial |
AppStore | Elic | Umemi |
reference
- ODR (1) : First look
- What is app thinning? (iOS, tvOS, watchOS)
- On-Demand Resources Guide