I’m trying to understand which storage capacity key is the correct one to use when deciding whether my app can start downloading offline video content.
I read the documentation here: https://developer.apple.com/documentation/foundation/checking-volume-storage-capacity
but I still don’t fully understand the intended usage difference between:
- volumeAvailableCapacityKey
- volumeAvailableCapacityForImportantUsageKey
My app allows users to download videos for offline viewing. These downloads may remain on the device for a long time (days or even months), so they are not just temporary cache files.
On one hand, this seems to match the description of “storing data based on a user request”, which suggests using volumeAvailableCapacityForImportantUsageKey.
On the other hand, my understanding is that this value may assume the system is willing to aggressively purge caches and reclaim space for this “important usage”. I’m worried this could lead to unexpected or unpleasant side effects for the user if my app relies on that space.
What confuses me even more is that the values are significantly different on my device:
- iPhone Settings reports about 142 GB free
- volumeAvailableCapacityKey returns only ~56 GB
- volumeAvailableCapacityForImportantUsageKey returns ~132 GB
So my question is:
For an app that downloads videos for offline playback — where the user explicitly requested the download, but the content may stay on device for a long time — which value is the recommended one to use when deciding whether there is enough free space to start the download?
Should offline media downloads generally be treated as “important usage” in the sense intended by this API?
I'll start with the short answer, then follow with more details:
Should offline media downloads generally be treated as “important usage” in the sense intended by this API?
Yes, you should be using "important". You might also look at the availability key, but mainly as a diagnostic tool to tweak your app’s behavior, not to fundamentally alter what you "do". For example, if you're downloading very large files very quickly, it's possible for you to be adding new important data to the device faster than the device can delete cache data, which will cause available to "spike" to a low value. If that happens, simply waiting for a little while may resolve the issue.
Similarly, if available and opportunistic are both "low" and your app stores large amounts of cached data, then you might want to delete your own cached data during/before you transfer in important data.
but I still don’t fully understand the intended usage difference between:
So, let me lay out the meaning of the three keys:
volumeAvailableCapacityKey-> This is "the truth". That is, how much free space the volume ACTUALLY has at any particular moment in time.
volumeAvailableCapacityForOpportunisticUsageKey-> This is the amount of space the system "thinks" is available to "cache stuff".
volumeAvailableCapacityForImportantUsageKey-> This is the amount of space the system "thinks" should be used to store actual user data.
Conceptually, the idea here is that the system will "fill up" currently unused space with cached data, then delete that data as needed by "important" usage. In technical terms, data the system can delete (like data stored in "Caches") or iCloud (because it's also stored in off-device) is considered "opportunistic", while everything else is considered "important".
That also means that this isn't really an issue:
On the other hand, my understanding is that this value may assume the system is willing to aggressively purge caches and reclaim space for this “important usage”. I’m worried this could lead to unexpected or unpleasant side effects for the user if my app relies on that space.
The practical definition of "opportunistic" is sufficiently narrow that this isn't data the user should ever be relying on. To put it bluntly, no app should be putting data the user "cares" about in "Caches".
Looking at your specific example:
volumeAvailableCapacityKey returns only ~56 GB
That's the actual state of the device currently.
volumeAvailableCapacityForImportantUsageKey returns ~132 GB
Most of that data (~76 GB) is cached data the system is perfectly happy to delete, so that's how much data it could store if it threw out most/all of its cached data.
iPhone Settings reports about 142 GB free
That's a number we're showing the user. I haven't looked at the EXACT of that calculation, but the system also maintains a bit of "extra" storage so that:
-
There's plenty of available storage for important usage to use while opportunistic data is being deleted.
-
There's some "extra" storage available to the user if/when the drive actually becomes "full" of important data.
...and I suspect that buffer is most of that ~10 GB.
Am I understanding correctly that as the device runs out of storage, the system has less reclaimable/purgeable space available, so the different capacity estimates start converging because there is simply less content that iPadOS can optimize or clean up automatically?
Yes, that's correct. More specifically, "availability" and "important" converge, while opportunistic goes to "0". There's some other nuance there in that the calculations are more complicated than they seem. The basic "available" number is easy, as the file system directly tracks its own "free" storage and we can just return that number. However, the problem with the other numbers is that it relies on determining how much space deleting an object will free, which is a trickier calculation than it seems.
Another interesting observation is that after reaching the values from Case 2, content downloads in many apps effectively stopped working.
Yes. Basically, "don't do that". The system operates as a database shared among "all" clients, and when it gets completely “full," that starts to break down. Your app should always ensure there's a significant "extra" buffer. Exactly how big that buffer should be depends on exactly what you're downloading and why, but I generally recommend at least 1 GB, and I would probably warn the user that space was becoming constrained while important got that "close".
One last comment on that last point. I would think very carefully about what size data you provide to the user and how you present it. If you present the number as a detailed, specific value, then:
-
Users will compare your number to Settings and other apps.
-
They will notice that it doesn't match and complain about it.
-
You will desperately try and make the values match.
...and that will continue until you eventually give up and do something else. The problem here is that you:
-
You don't have access to the exact calculation Settings.app is making.
-
Available storage fluctuates enough that even WITH the exact calculations, the numbers still wouldn't always match.
In my experience, the simplest solution to these issues is using your device’s state as an example, saying "100+ GB" is just as useful to the user, while sidestepping any comparison between your app and the rest of the system.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware