iOS: Prevent files from being removed on low disk space

My app downloads a number of files from my internet server, and caches those in the app, such that they are available when off-line. Recently, a couple of customers have complained that (the data originating from) those files sometimes disappears from the app. After long research, I am now reasonably certain that it is iOS which removes the files when disk space is low. I am trying to find a way to prevent that from happening.

The files are currently located in a subdirectory of Library/Caches, which seems the most appropriate place for these files. Note that there is no need to back-up the files to iTunes or iCloud.


I have searched the internet for ways to prevent this removal, but get conflicting information, and cannot find a clear statement from Apple. The most useful info from Apple itself, is the following:

https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW1

which says that: "the contents of this directory are not backed up by iTunes or iCloud". It also says that: "In iOS 5.0 and later, the system may delete the Caches directory on rare occasions when the system is very low on disk space." - which is exactly what I am trying to avoid.


But then the following StackOverflow post: https://stackoverflow.com/a/27309392/908621 says that the removal of files is based on whether they can be restored from iCloud backup. The "NSURLIsExcludedFromBackupKey" property should be set to prevent files from being removed.


So my explicit questions for files that do not need to be backed up, but should also stay on the device under low disk space conditions:

- Is the Library/Caches the correct place for these files - if not, what other location is better?

- Is it required and sufficient to set the "NSURLIsExcludedFromBackupKey" for those files (even though files in Libary/Caches are not backed-up anyways according to Apple)?

- Is it sufficient to set the "NSURLIsExcludedFromBackupKey" on the directory the files are in?

- How can I test all this?

Replies

Direct quote from the documentation:

In iOS 5.1 and later, store support files in the <Application_Data>/Library/Application Support directory and add the NSURLIsExcludedFromBackupKey attribute to the corresponding NSURL object using the setResourceValue:forKey:error: method. (If you are using Core Foundation, add the kCFURLIsExcludedFromBackupKey key to your CFURLRef object using the CFURLSetResourcePropertyForKey function.) Applying this attribute prevents the files from being backed up to iTunes or iCloud. If you have a large number of support files, you may store them in a custom subdirectory and apply the extended attribute to just the directory.

Is the Library/Caches the correct place for these files - if not, what other location is better?

No. If you put stuff in the Caches directory the system is free to delete it when necessary (although it won’t delete it while your app is running). If you don’t want that, don’t use the Caches directory.

Is it required … to set the

NSURLIsExcludedFromBackupKey
for those files …?

The Caches directory is never backed, so if you leave the files where they are then the answer to your question is “No.” However, it sounds like you’re doing to move the files to a different directory, and if you do that then the answer changes to “Yes.”

Is it sufficient to set the

NSURLIsExcludedFromBackupKey
on the directory the files are in?

Yes (per the documented that TheCD quoted).

How can I test all this?

There’s two aspects to this:

  • Testing cache purge (A)

  • Testing backups (B)

With regards A, there’s no explicit way to purge caches (although that’d make a fine enhancement request against Settings > Developer) but you can achieve roughly the same result by creating a test app that wastes disk space. Once disk space gets low enough, the system should start purging caches.

The best way to test backups (B) is to back up the device, erase it, restore it from the backup, and see if the files are present. You can also take various shortcuts here:

  • If the files are large, you can do an iTunes backup and look at the size of that backup. If these large files are getting backed up, you’ll be able to see that reflected in the size of the iTunes backups.

  • Unencrypted iTunes backups use a relatively easy-to-reverse-engineer format, and there are lots of unsupported third-party tools out there that will let you see their contents.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks, TheCD

I noticed that as well. But the question is: if I set the NSURLIsExcludedFromBackupKey for these files, will that prevent them from being removed in low disk-space situations?

Thanks for the fast and extensive response, Quinn.

Just to be sure, can you explicitly confirm that: if the files are stored in a subdirectory of "Library/Application Support", and NSURLIsExcludedFromBackupKey is set for the subdirectory, then iOS will never remove the files, also not in low disk-space situations?


Many thanks, René

According to the documentation I linked to, the system always preserves files in /Documents and /Library (excluding /Library/Caches). Thus, if you store files in /Library/Application Support, they will not be deleted by the system.

The

NSURLIsExcludedFromBackupKey
key is irrelevant in this case; iOS will not spontaneously delete files from your container except for specific directories, like Caches.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I have the same problem. My app downloaded files to Library/Caches folder and clients started to complain that these files had been disappeared.

Now I create a folder with the name of bundleId in Library/Application Support folder and set the NSURLIsExcludedFromBackupKey to it. All downloaded files are stored in subfolders in this folder. But testers still complain that the files are disappeared.

This occures in iOS11 only (not tested on ios12 yet). The more interesting thing is that there is about 6GB of free space but iOS shows "Storage alomst full" alert and deletes files in my app.

What am I doing wrong? Is it enough to set NSURLIsExcludedFromBackupKey to my folder or I need to set it recursively to each file in each subfolder?

Is it enough to set

NSURLIsExcludedFromBackupKey
to my folder … ?

Yes. However that’s irrelevant because that’s not the problem you’re testers are reporting. If you’re testers were saying that their backups are being bloated by these large files, then you’d want to look at the behaviour of

NSURLIsExcludedFromBackupKey
. However, the testers are saying that these files are being spontaneously deleted, and
NSURLIsExcludedFromBackupKey
has no impact on this.

I don’t have any specific advice on what’s going on with your app. If you can’t figure it out I recommend that you open a DTS tech support incident and discuss it with one of my colleagues, who has a lot of experience with issues like this.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"