According to the documentation, iOS 9 on-demand resources downloaded through a NSBundleResourceRequest are kept only until endAccessingResources
is called, and it is called automatically when the resource request object is deallocated.
Okay, but when the app terminates, everything is deallocated. So does this mean that resources downloaded using a NSBundleResourceRequest don't survive termination of the app? I was hoping to use a simple strategy of making my app smaller for download from the App Store by not including a lot of the resources, and then downloading them later; but that's not going to work if I'm not able to keep those resources. Am I expected to copy the resources somewhere else and release the NSBundleResourceRequest?
When you endAccessingResources
, the asset becomes eligible for purging (assuming there are no other requests holding a retain on it). However, reading the documentation for ODR, it doesn't necessarily follow that the assets will be removed from the device immediately:
An asset pack is eligible for purging when all of the associated tags are no longer retained by any request. The resources associated with a tag may remain on the device for some time before it is purged, including across app launches.
So the resource might survive your app termination and still be there the next time your app opens, depending on whether the OS feels it needs to free up the space or not. If you use conditionallyBeginAccessingResourcesWithCompletionHandler
to access resources, you will get a boolean telling you whether the resource is still on the device. If it is, you can start using it immediately; and if it isn't, you can initiate a download with beginAccessingResourcesWithCompletionHandler
.
If you want to guarantee that the resource will always be there, you could include it in the initial download; or, if you definitely want to use ODR, you have to make a copy of the downloaded resource somewhere else to persist it.
However, making a copy of the resource might mean that you end up with 2 copies on the device - one that you have copied and persisted, and one that the OS has not yet deleted. After you have copied all the ODR resources, it might be that the app takes up twice as much space as it would have if you just copied everything in the initial download, at least until the OS decides it should purge the assets.
Having used ODRs on tvOS, it seems that the OS tries to keep assets in the cache, so that, on the next use of the app, as much data as possible is still there without needing to be redownloaded (there may be complicated algorithms in the background determining the likelihood of a user using an app again in the near future). This approach of "we'll keep as much data in the cache as we can" is great if the app doesn't persist assets elsewhere, but seems a bit unnecessary if the app is going to copy the assets and guarantee they persist.
Ultimately, the cache will get automatically purged if there is a memory issue, so it is only a cosmetic issue where users will potentially see your app as being larger than they expected, and then at some point down the line, it will be magically smaller.
I ended up doing exactly what the question suggests in its last sentence: when the resources arrive, I copy them into the Application Support folder and release the NSBundleResourceRequest.
This seems somewhat against the spirit of on-demand resources, but in my opinion that spirit is the wrong spirit; this feature is not designed in a very practical way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With