iCloud and the new iOS Data Storage Guidelines
Guys, we need to talk about something serious today: Rejection.
I know it’s tough, but every once in a while, you’ve got to face it. The dreaded App Store Rejection. Today one of my apps was rejected because I didn’t meet the new guidelines for data storage.
More specifically, I had developed a way for a Core Data db to arrive prepopulated inside an app on first launch, and was storing that data in the app’s Documents directory, which used to be all good. But with the advent of iCloud and iCloud-based iOS backups, it looks like Apple is putting restrictions on where you can store this kind of data. And rightfully so.
With the way I previously had the app configured, it would copy a preloaded, bundled version of the main Core Data sqlite database over to the Documents directory. This was put in place because the app is very image-heavy, and downloading all the necessary images on first launch made for a poor user experience. The problem with this is that the new Data Storage Guidelines state that this approach is far from kosher:
Data that can be downloaded again or regenerated should be stored in the<Application_Home>/Library/Caches directory.
D’oh.
So let’s go over the new rules, shall we? Here’s a summary:
- Critical data that cannot be recreated, such as documents or user-specific data that would be lost if the device were damaged, goes into the <Application_Home>/Documents directory and will be backed up by iCloud unless otherwise specified.
- Cached data that can be recreated, such as a local database or downloaded images, goes into the <Application_Home>/Library/Caches directory and will not be backed up by iCloud. This data may get purged at some point if iOS runs low on disk space.
- Temporary data that is transient and not used between app launches, such as a temporary file cache, goes into the <Application_Home>/tmp directory and will not be backed up by iCloud. You should always remember to delete files stored here yourself.
- Offline data that needs to be persistent and available when the device is offline (such as Airplane Mode), goes into the <Application_Home>/Library/Private Documents directory and will not be backed up by iCloud, but also will not be purged by iOS in a low disk space situation. For more information about Private Documents in iOS, see QA1699.
Keep these in mind, because a deviation from any of these items will cause your app to be rejected.
It makes sense, with the new iCloud backup system, why they would want to put some constraints on what data is stored in which directory. This way my 15 MB pre-populated database doesn’t get backed up to the user’s iCloud account, taking up precious limited space. It would also cause a bit of a drag on the wireless backup process.
When it was all said and done it was a quick and easy fix, the sting of rejection notwithstanding, and the app is resubmitted. For all of you iOS devs that might be facing a similar problem, here’s a method you can use to quickly find your application’s cache directory and ensure you’re 100% kosher with the iCloud/iOS Data Storage Guidelines. I suggest putting it in your AppDelegate:
- (NSString *)applicationCachesDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachePath = [paths objectAtIndex:0];
BOOL isDir = NO;
NSError *error = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDir] && isDir == NO) {
[[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:nil error:&error];
}
return cachePath;
}
Another lesson learned for me today: Always stay on top of the documentation with every major release. Hell, stay on top of the documentation with every minor release. There’s no good reason to fall behind, especially when your app’s life depends on the rules.
Posted from New York, New York, United States.
4 Responses to iCloud and the new iOS Data Storage Guidelines
Leave a Reply Cancel reply
-
Categories
-
Meta
I should have read this earlier
Do I understand correctly that you are storing images inside Core Data? That’s safe to put in the cache directory, but what if you also store other things in the database? I.e. “critical data”.
Do you have to split the database and use two NSPersistentDocuments, one in the documents directory and one elsewhere?
I posted the same question on the Apple forum:
https://devforums.apple.com/message/595188#595188
I hear you on reading things earlier. I’ve read a lot of blog posts that would’ve saved me TONS of time, and it’s always like…facepalm. Such is life as a developer. There’s always room for improvement.
Yes, I am storing images inside of Core Data, as NSData. It’s actually really easy, because UIImage can convert from NSData with one line.
So what I ended up doing (and this reminds me I should probably update the post) is putting the sqllite file back in Documents, but marking it as a file that should not be backed up. This fulfilled both requirements: That the data be persistent, not cleared out when iOS is low on space and trashing cache files, and the App Store review requirement that large files not be backed up by iCloud.
In other words, you can keep your stuff in the main Documents folder, but be sure to mark it as not to be backed up. You can do that by using the method from the example here:
http://developer.apple.com/library/ios/#qa/qa1719/_index.html#//apple_ref/doc/uid/DTS40011342-CH1-DontLinkElementID_4
Thanks for the suggestion. But what if we want do want our “critical data” to be included in the backup? The only solution then seems to be splitting the database to use two sqlite files; both in /Documents and one of them marked as “no backup”.
That creates a whole set of new problems though…
My app also got denied for the same reason. I have 5 folders containing 200 PDF maps that are necessary to the operation of the map viewer program. I can move them very easily and to the correct folder but fortunatly there doesn’t seem to be a way to set the folders “do not back up attribute” in the language that I used to develop the app. Livecode. SO I may be screwed until livecode comes up with a fix.
Bummer.
Dave