iOS Data Storage Guidelines issues for a backwards-compatible app - ios

I'm developing an iOS app that has to support iOS 5+. I've read the iOS Data Storage Guidelines in order to prepare the app for the submission and read several questions and solutions about those guidelines here in Stackoverflow, but I still have some doubts about how I should handle this.
I have an sqlite database whose tables are defined in an .sqlite file. I copy this file into \Documents folder when app starts, and I keep such file always there in \Documents. This database firstly contains some collections of fixed data that app may need (lists of cities to select and things like that), and the rest is user-dependent data that will be downloaded. I've read this post: Apps must follow the iOS Data Storage Guidelines or they will be rejected in app that contains .sqlite3, but I still don't know what criteria should I apply. The .sqlite is not downloadable, it is included in Supported Files of the Xcode project, and some of the initial data is inserted from inside the app and it is neither downloadable. The user-dependent data, well, I can download it whenever I need. I've not integrated any iCloud stuff in my app. So, should it be correct to keep the .sqlite file always in Documents? AFAIK, you need the file to be there for performing all database operations...
As I said, I've not included any iCloud related code in my app, and in fact I donĀ“t know how iCloud is managed because I've never told to do it, are backups of the app made anyway? Should I use the flags the iOS Data Storage Guidelines says in order to prevent files to be backuped? I need some guidence regarding backups and iCloud considerations.
And there is another thing: my app also downloads some user-dependent images. I show them in several views throughout the app, so I need them to persist while the normal working of the app. However, it is downloadable content. So, where should I place them?
Thanks a lot!

I believe your .sqlite file should be in Documents, this is the correct place for it.
You downloaded images should probably be in Caches, but you could also get away with them in documents as long as you set the "do not backup" attribute.
You can set the skip backup attribute like this:
BOOL success = [url setResourceValue: [NSNumber numberWithBool: skip]
forKey: NSURLIsExcludedFromBackupKey error: &error];

Related

(iCloud) How to programmatically Backup/Restore data for all Apps like iTunes does?

I'd like to backup and restore files (or other type of informations like key-value, SQL-like transaction based info.) for NOT ONLY my app but also all the other Apps using iCloud.
I'm just new to iCloud and read only a few documents but it seems iCloud APIs are just for single App boundary (of course I understand there is an option for sharing information between 'Group' of applications).
What I want to do is backup and restore almost everything. How can I do that?
(There some apps doing this like
http://www.copytrans.net/copytranscontacts.php
http://www.macrumors.com/2012/05/18/elcomsofts-phone-forensics-software-offers-near-real-time-access-to-icloud-backups/)
I checked that the some of the Mobile App files are stored inside the "~/Library/Application\ Support/MobileSync/Backup" directory but there are only some of the files from all the files actually stored in iCloud.
And I tested CloudKit, but it just takes control over App's own data only.
Thanks in advance.
One thing to keep in mind when thinking about this is that iTunes actually doesn't backup or restore anything to/from iCloud. iOS device does it on its own: there's a daemon process running and if iCloud Backup is enabled, it will backup directly to iCloud, without talking to iTunes. Restore is also done without interaction with iTunes.
Next, as #rmaddy pointed out, your app on the device cannot access files of other apps, so you won't be able to do what you want from the device. If you want to do this via companion app running on PC/Mac then it might be possible, but will depend on what exactly do you need/want.
Re: contacts. Apps can access AddressBook and thus can sync/upload its contents. Apps can also access some other shared data, such as Photo Library. This is still a far cry from your original request to "Backup/Restore data for all Apps".
Re: downloading iCloud backups. Downloading isn't a big deal those days (Disclosure: I am the author of that forensic tool to download iCloud backups you're mentioned). There is even an open-source code for that. However, downloading and restoring are two very different processes. Specifically, you can download, but your app won't have enough permissions to write files in place.
Hope this helps and clears things up.

Should I follow iOS Data Storage Guidelines?

My iOS app is intended to be compatible with iOS 5.0 and above, and it has iCloud capabilities turned off in it's target settings, I'm not integrating with iCloud. My app stores an sqlite file and some image files into Documents folder. The sqlite file is not downloadable, but images are.
I've read some posts from people saying that their app's submission was rejected because they don't met the iOS Data Storage Guidelines, but I'm not sure if that is only required if your app has iCloud capabilities enabled, is it? Should I set the NSURLIsExcludedFromBackupKey for my files anyway?
Thanks in advance
EDIT
I've read this here:
It is not possible to exclude data from backups on iOS 5.0. If your app must support iOS 5.0, then you will need to store your app data in Caches to avoid that data being backed up. iOS will delete your files from the Caches directory when necessary, so your app will need to degrade gracefully if it's data files are deleted.
But I need the sqlite file to be in Documents to insert data... how should I handle this?
It has nothing at all to do with whether your app uses iCloud or not. It has to do with the user performing backups to iCloud which is beyond the control of your app.
If all of the data in your app that is stored in the app sandbox is data that is created and stored by the user through the use of the app then Apple will have no problem with the data being backed up.
They have issue with replaceable files being backed up needlessly. If the database file is read-only and could be obtained from a server or the app bundle then don't let it be backed up. But if it starts out mostly empty and then gets data added as the user adds data through the app then it should be backed up. Same for the images.

Are NSPersistentDocument and UIManagedDocument compatible?

I would like to create a NSPersistentDocument in Mac OS X and read this document as a UIManagedDocument on iOS 7.
Is this possible?
Are both file formats compatible?
Thank you!
Interesting question - I can confirm that the basic core data files are compatible. I have a Mac app and an iOS app using the same file that gets synced using iCloud. The app is a document based app and currently I have been storing the actual database file in iCloud so the whole file gets sync'ed by iCloud.
This works fine but obviously if a user opens the file on two devices and is not careful about saving and closing there is a possibility their changes may be overridden.
Apple has approved the Mac app which uses standard NSPersistentDocument to create and save files. Unfortunately they have rejected the iOS apps with some obscure reference to not conforming to their data storage guidelines, saying that documents must be stored in /Documents directory if they need to be backed up to iCloud. Well if the user has selected iCloud then I store the files in the iCloud location provided by the API calls.
Anyway I am still waiting to hear back from them about what is specifically wrong with this approach since it seems to be the same one used by Pages and other document based apps.
If I try using UIManagedDocument then iOS creates a folder structure and stores the database inside this folder structure. The Mac app File->Open dialog then shows this folder structure as well as a file that essentially looks like a the normal sqlite file. But then perhaps OS X 10.8.4 does not implement the latest iCloud/Core Data stuff - who knows...
EDIT
Here is a link to code examples and videos showing OSX and iOS app integration using Core Data and iCloud. http://ossh.com.au/design-and-technology/software-development/uimanageddocument-icloud-integration/
I agree this is definitely possible. I'm using NSPersistent document on OS X 10.8/10.9/10.10 with a binary core data format (no wrappers - plain files). On iOS i'm using UIDocument. Core data works fine in both environments.
Apple says NSPersistentDocument does not support iCloud. It is more correct to say it isn't fully supported. Most of the NSDocument support (which includes iCloud Document Library access from 10.8) will work. Handling of conflicted files on open works.
You can't enable auto save (which is listed as a requirement for iCloud Documents in the iCloud Design Guide). Autosave works asynchronously and is definitely not supported by NSPersistentDocument.
So if you handle file saving, and conflicts, it is possible to use NSPersistent document. There are some quirks: so, for example, if an iCloud change arrives on OS X for a document that is open, the normal NSDocument response would be to automatically reopen the document. This doesn't happen - and there is no warning the file has changed until you are about to save the file. But at least there is a warning. On iOS it is easier to detect changes as they happen by using UIDocumentStateChangedNotification.

Which technique will be better to store IOS app data and run app in offline mode??Documents directory or cache directory or temprary directory?

Hi recently my app has been rejected by APPLE, they says
We found that your app does not follow the iOS Data Storage Guidelines, which is required per the App Store Review Guidelines.
In particular, we found that on launch and/or content download, your app stores 3.11 MB. To check how much data your app is storing:
- Install and launch your app
- Go to Settings > iCloud > Storage & Backup > Manage Storage
- If necessary, tap "Show all apps"
- Check your app's storage
The iOS Data Storage Guidelines indicate that only content that the user creates using your app, e.g., documents, new files, edits, etc., should be backed up by iCloud.
Temporary files used by your app should only be stored in the/tmp directory; please remember to delete the files stored in this location when the user exits the app.
Data that can be recreated but must persist for proper functioning of your app - or because customers expect it to be available for offline use - should be marked with the "do not back up" attribute. For NSURL objects, add the NSURLIsExcludedFromBackupKey attribute to prevent the corresponding file from being backed up. For CFURLRef objects, use the corresponding kCFURLIsExcludedFromBackupKey attribute.
For more information, please see Technical Q&A 1719: How do I prevent files from being backed up to iCloud and iTunes?.
It is necessary to revise your app to meet the requirements of the iOS Data Storage Guidelines.
For discrete code-level questions, you may wish to consult withApple Developer Technical Support. Please be sure to:
- include the complete details of your rejection issues
- prepare any symbolicated crash logs, screenshots, and steps to reproduce the issues for when the DTS engineer follows up.
For information on how to symbolicate and read a crash log, please see Tech Note TN2151 Understanding and Analyzing iPhone OS Application Crash Reports.
If you have difficulty reproducing this issue, please try testing the workflow as described in https://developer.apple.com/library/ios/qa/qa1764/TestingWorkflow with Xcode's Archive feature".
What should i do now??Need Help
I have also face the same issue. To resolve this issue you should do some code so that your DocumentDirectory should not sync with iCould. For that you have to set one flat to your DocumentDirectory which is known as Don't BackUp.
To achieve that use code provided by the Apple..
To know more then you can refere this.
Hope this will help you.
All the best !!!
Basically, what Apple is telling you that only documents that the user expressly creates and wants to save are what should be stored in iCloud.
Otherwise, you can save the files your app creates to the "Documents" directory (if you want it to persist between launches) or the Temporary folder (if you don't care what happens to the files between the device being powered up and down).
And in connection with Yashesh's answer (+1 to him!), make certain that iCloud is turned off by going to the Target (app) settings and turning the "iCloud" checkbox to off, like this:

What directory should I store analytics data in on iOS?

I'm trying to store analytics data that is saved locally about a user's actions so it can be uploaded later when the user has an internet connection. I'd like the data to be stored locally and not deleted between subsequent opens of the app under normal circumstances. I do not want the data to be synced to iCloud. I'd also ideally like the data to be preserved between updates. It's fine if the data gets deleted in cases of low space.
I'm getting different answers from different sources about where to store the data- either in NSCachesDirectory or NSLibraryDirectory. Note NSCachesDirectory is a subdirectory of NSLibraryDirectory, eg. the filesystem looks like Application_Home/Library/Caches/.
According to the official documentation: http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/PerformanceTuning/PerformanceTuning.html#//apple_ref/doc/uid/TP40007072-CH8-SW9 implies I should use NSCachesDirectory to store the data and it is not deleted under most circumstances. It also implies NSLibraryDirectory is synced to iCloud.
According to these answers: How can I get a writable path on the iPhone?, https://stackoverflow.com/a/5444762/340520/, When are files from NSCachesDirectory removed?, NSCachesDirectory is not preserved between app updates and claims that I must constantly recreate the NSCachesDirectory. The first answer also implies NSLibraryDirectory is the best place to store the data. However those answers are two years old.
According to the documentation and this answer: http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/PerformanceTuning/PerformanceTuning.html#//apple_ref/doc/uid/TP40007072-CH8-SW10, https://stackoverflow.com/a/8830746/340520, NSCachesDirectory ARE preserved between app updates.
Localytics' iOS SDK stores their data in NSCachesDirectory: https://github.com/twobitlabs/Localytics-iOS/blob/master/src/LocalyticsDatabase.m
Mixpanel's iOS SDK stores their data in NSLibraryDirectory: https://github.com/mixpanel/mixpanel-iphone/blob/master/Mixpanel/Mixpanel.m
Between all these sources, I've been leaning toward using NSCachesDirectory, but I'm not confident that the data won't get regularly deleted under some circumstances.
NSCachesDirectory is the wrong place to store persistent information that you will need across app starts or even device re-starts.
To prove my point try this ...
Get a iPhone device that has only 8GB disk space.
Use your app to write a file in the NSCachesDirectory.
Start downloading random apps to fill up the disk space. Very soon you will see the Storage limit dialog shown by the OS.
Now just re-start your phone, start the app and see if you can find your file that you wrote.
If the first time you find the file, try the experiment again and you will find your file missing. During the device startup, if you see the device logs you will notice logs indicating purging directory to make space etc.
Use NSCachesDirectory to store information you can keep downloading from your server. Not information that you need to upload to your server.
The Caches directory should only be used for files that your app can easily replace if they are deleted. The Caches directory is may or may not be purged during an app update and possibly if the device runs out of storage space. Only use this for temporary files or files you can easily replace.
My first choice would be the Library/Application Support directory (NSApplicationSupportDirectory). Please note that this directory is not created by default. Your app must create it on first startup. This path is kept during app updates (like most of the app sandbox) and it is backed up via iTunes (or iCloud) device backup.
I think the best place is Library/Application Support (NSApplicationSupportDirectory) refer How do I prevent files from being backed up to iCloud and iTunes? for details.

Resources