iOS storage best practices
This article talks about the common locations where your iOS application can store files in.
Following are the sections in which an iOS application sandbox is divided
Bundle Container : This is the application’s bundle. This directory contains the application and all of its resources.You cannot write to this directory. To prevent tampering, the bundle directory is signed at installation time. Writing to this directory changes the signature and prevents your app from launching.The contents of this directory are not backed up by iTunes or iCloud. However, iTunes does perform an initial sync of any apps purchased from the App Store.
Data container :
Here we have following directories where application can store data
- Documents Directory — Store only those files in here which should be visible to the user.Contents of this folder is visible in the “Files” application provided it supports “Open in place” and “File sharing” is enabled.Content of the directory is persisted and included in the iCloud and iTunes backups. Disk space used in this directory is reported in the storage settings UI under your app’s “Documents and Data” total.
- Few benefit of exposing the “Document directory” are files become visible in “Files” application and user can find their files in spotlight.
- You can store files at the top level or you can create sub-directories. If you choose to create a sub-directory then keep in mind that not all names are allowed for directory name. I guess few directory names are reserved by Apple as I was not able to create an “Inbox” directory but rest all names that I tried worked.
Note — To enable “Open in place” add “Application supports iTunes file sharing” or “UIFileSharingEnabled” key with value “YES” in Info.plist and to enable “File sharing” add “LSSupportsOpeningDocumentsInPlace” or “Supports opening documents in place” key with value “YES” in Info.plist.
- Library / Application Support Directory — Store files in here that are required for your app but should never be visible to the user like your app’s database file.You can store files in here at the top level or create sub-directories.Content of the directory is persisted and included in the iCloud and iTunes backups.You can opt files out if they don’t need to be backed-up.Disk space used in the application support directory is reported in the storage settings UI under your app’s “Documents and Data” total.
Note — Unlike other directories mentioned here, “Application support” directory is not present by default in you application’s “Data container” and you need to create it first.
- Library / Cache — Stores files in here that can be discarded when the space is low.This is a good location for any content that can be re-downloaded when needed.Contents of this directory is not included in the backups.When the device is low on disk space then iOS can help by clearing caches.Files will never be removed from your cache if your application is running and OS will start by clearing caches from apps that haven’t been used in a while.Files stored on the caches directory is not reported in the storage settings UI under your app’s “Documents and Data” total.
- tmp — Put files in here that your won’t be needing for extended period of time.Even though operating system will periodically remove these files when your app is not running, it’s best to remove them when you are done with them.Like the cache directory, tmp directory is not backed up and is not reported in your apps “Documents and Data” total.
iCloud container:
iCloud drive is the best place to put document because they become available on all of the user devices. Contents of your application folder is visible on the iCloud Drive. Your application reads and writes data locally and when the network is available data is uploaded automatically to iCloud drive. Since multiple devices maybe be accessing the files present in the iCloud drive at the same time, file coordination is required to avoid any conflict.
Note — Use iCloud drive and Documents directory for the files that should be accessible in the “Files” application while Application Support, cache and tmp directory are all used by your application privately.
Best Practices
- If you have files that don’t need to included in iTunes and iCloud backups, set the URLResourceValues’s, “isExcludedFromBackup” property as “true”.
- Be sure to store file only at one location i.e. either locally or on iCloud drive. If you put files in your local document directory don’t duplicate those in iCloud drive. For user document iCloud storage location is preferred unless you have a specific reason to store files only local to a device.
- Be resilient to files that might be restored from the older version of the application. i.e. If you had a 32 bit version of your application and it’s files were backed up then for a 64 bit version of your application those older file might get restored and you need to be able to handle that situation. It’s best to use a versioning scheme on your files so that you can provide robust compatibility across multiple versions of the application.
- Checking Volume Storage Capacity — Before you try to store a large amount of data locally, first verify that you have sufficient storage capacity. To get the storage capacity of a volume, you construct a URL (using an instance of URL) that references an object on the volume to be queried, and then query that volume.The query type to use depends on what’s being stored. If you’re storing data based on a user request or resources the application requires to function properly (for example, a video the user is about to watch or resources that are needed for the next level in a game), query against NSURLVolumeAvailableCapacityForImportantUsageKey. However, if you’re downloading data in a more predictive manner (for example, downloading a newly available episode of a TV series that the user has been watching recently), query against NSURLVolumeAvailableCapacityForOpportunisticUsageKey.
How to review where your app is storing its data?
- From Xcode menu click on “Window” and then on “Devices and Simulators”.
- Select your device from list in the left panel.Select your the app from the list of installed applications on the device
- Using the gear icon choose download container and save it on your Mac.
- In the finder ctrl+click on the “xcapppdata” file that was downloaded and select “Show package contents”.
- Go into the AppData folder to start taking inventory.
Why iterate through multiple URL objects to find a “standard directory?”
To get path/URL of any of the standard directory, we can use one of the following methods.
urls(for directory: FileManager.SearchPathDirectory, in domainMask: FileManager.SearchPathDomainMask) -> [URL]
or
NSSearchPathForDirectoriesInDomains(_ directory: FileManager.SearchPathDirectory, _ domainMask: FileManager.SearchPathDomainMask, _ expandTilde: Bool) -> [String]
Both of these methods returns an array of URL.So why these API returns multiple URL objects as an iOS application will have only one copy of any of the above mentioned standard directories ?
It’s a result of providing cross-portability with macOS. You may have multiple domains on a possibly multi-user device like a MacBook Pro and for such devices these APIs can take an array of domain masks as parameter and then return an array of URLs for the requested standard directory in all specified domain masks.
e.x. — “FileManager.default.urls(for: .applicationSupportDirectory, in: [.userDomainMask, .systemDomainMask])”
On an iOS device, you’re most likely confined solely to the “.userDomainMask” because of sandboxing, though this may change in future iOS versions.
That’s it for now and i hope you find this helpful. Thanks for reading. 😀😀😀
Resources for this article:
https://developer.apple.com/videos/play/tech-talks/204/
http://iosbrain.com/blog/2018/05/29/the-ios-file-system-in-depth/