iOS Data Storage Guidelines quick guide
A lot of people are having this problem and often it seems that the review team is automatically claiming that your app does not follow the iOS Storage Guidelines. Either way you need to document where your app store data and what data is stored where. Here's a quick guide that should get you started.
Your app can store files in either /Documents, /Library or /tmp.
Documents/
Use this directory to store user-generated content. The contents of this directory can be made available to the user through file sharing; therefore, his directory should only contain files that you may wish to expose to the user.
The contents of this directory are backed up by iTunes.
Library/
This is the top-level directory for any files that are not user data files. You typically put files in one of several standard subdirectories. iOS apps commonly use the Application Support and Caches subdirectories; however, you can create custom subdirectories.
Use the Library subdirectories for any files you don’t want exposed to the user. Your app should not use these directories for user data files.
The contents of the Library directory (with the exception of the Caches subdirectory) are backed up by iTunes.
tmp/
Use this directory to write temporary files that do not need to persist between launches of your app. Your app should remove files from this directory when they are no longer needed; however, the system may purge this directory when your app is not running.
The contents of this directory are not backed up by iTunes.
Put user data in Documents/.
This is backed up by iTunes/iCloud
Put app-created support files in the Library/Application support/
This is backed up by iTunes/iCloud
Put temporary data in the tmp/ directory.
This is not backed up by iTunes/iCloud
But how do I find out where my files are stored?
Put the script bellow in func application:didFinishLaunchingWithOptions in your appDelegate file. NSSearchPathDirectory is an enum and represents different folder/locations. Some of them are these.
public enum NSSearchPathDirectory : UInt {
case DocumentDirectory
case LibraryDirectory
}
Change the NSSearhPathDirectory(.DocumentDirectory) to desired locations and check what files you are storing there.
let paths: NSArray = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true)
if let documentDirectory = paths.firstObject{
do{
let documents = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(documentDirectory as! String)
for files in documents {
let urlForm = NSURL.fileURLWithPath((documentDirectory as! String) + "/" + files)
do{
try print("\(files): \(urlForm.resourceValuesForKeys([NSURLIsExcludedFromBackupKey])), with filepath: \(urlForm)")
//Prints out folder and files in the desired location
} catch let error as NSError{
print("Can't find key: \(error)")
}
}
}catch let error as NSError{
print("Can't retrieve contents: \(error)")
}
}
My app does not save anything
Lucky you...Write a document to the Apple review team and document your app use of storage. Take screenshots from the logs made out from the script above.
My app saves a lot of user created data
If your app saves a user's data to Documents/ that is fine and write a document documenting that this is made by the user and do follow the iOS Data Storage Guidelines.
If your app downloads data and saves it to the wrong location
Simply follow the iOS Data Storage Guidelines and submit a new binary.
I have files in Documents/ or Library/, but I don't want to back them up
Starting in iOS 5.1, apps can use either NSURLIsExcludedFromBackupKey or kCFURLIsExcludedFromBackupKey file system properties to exclude files and directories from backups. Apps that need to exclude a large number of files can exclude them by creating their own sub-directory and marking that directory as excluded. Apps should create their own directories for exclusion, rather than excluding the system defined directories. Either of these APIs is preferred over the older, deprecated approach of directly setting an extended attribute. All apps running on iOS 5.1 and later should use these APIs to exclude data from backups.
I've created a quick script to handle files that you don't want to backup.
func addSkipBackupAttributeToItemAtPath(filepath: String)-> Bool {
if let url: NSURL = NSURL(fileURLWithPath: filepath) {
let exist = NSFileManager.defaultManager().fileExistsAtPath(String(url))
if exist{
do
{
try url.setResourceValues(["YES" : "NSURLIsExcludedFromBackupKey"])
return true
}
catch let error as NSError
{
print("\(error)")
return false
}
} else
{
print("File does not exist")
return false
}
} else
{
print("Path not recognized")
return false
}
}
If you believe your app's rejection is false write the review team back and explain the situation and your use of storage
Simple guidelines
Bandwidth, network availability, and storage are limited resources and have real, financial consequences for your users. When you design your schema, store in iCloud only information that can’t be re-created.
iCloud-enabled Core Data apps are not only aware of data created on the device, they’re aware of data on other devices. It’s a good idea to keep this fact in mind when designing your Core Data stack.
When you save a managed object context, Core Data creates, in the ubiquity container, a set of transaction changes that are guaranteed to be applied together on other peers. The size of this transaction set, and the frequency with which you save your context, both directly impact the performance of your app.
Resources:
iOS Data Storage Guidelines - Apple Developer
iCloud Programming Guide for Core Data
File System Programming Guide