46

I have made an application for my client by keeping target iOS as 4.
But since the application still not submitted to Apple store, my client is planning to upgrade it for iOS 5.0.

For this I read the guideline from Apple and found that "Only user-generated data or that cannot otherwise be recreated by your application, should be stored in the /Documents directory and rest should be stored to /Library/Caches directory"

In my application, I am using server model of in-app purchase for non-consumable product. For this I am storing all my downloaded data (which are basically books or magazines) to Documents directory. The Database is also present in the same directory which contains the details about the downloaded products.

My question is,
1. Should I have to change my code to store the downloaded data to Library/Caches directory instead of to the Documents directory?
2. Where should my database file be placed (to Documents or Caches)?

If I put it products in the Caches then I have to change the logic of retrieval also, since it is considered that if record is present in database, there is no need change the existence of the file and it directly opens it when user clicks on the magazine.

Kindly guide me on this issue.
Thanks in advance.

UPDATED:
I am updating this for those who are still not sure about this problem.
Using the guideline of accepted answer, I have implemented this in 2 of my applications and submitted them to Apple Store. Both were approved in review.
This may promote that the solution suggested in the accepted answer is correct.

Naved
  • 4,020
  • 4
  • 31
  • 45

6 Answers6

57

Here are the trade-offs:

  • If you put your files in the Documents directory then they are backed up to iTunes or iCloud but if they are too big and it's possible to download the files again then Apple may reject your app
  • If you put your files in the Cache directory then they won't be backed up and Apple won't reject your app. However, when iOS 5 gets low on space it may delete all the files in there.

However, with iOS 5.0.1 there is a third option:

  • Put files in Documents but flag them so that they are not backed up. There's a technote (QA1719) on how to do this.

I think this is probably the best answer for you.

Stephen Darlington
  • 51,577
  • 12
  • 107
  • 152
  • +1 for the third option. Thank you very much for your reply. However, I will have to first confirm it with the client and analyze it before explaining the same to the client. – Naved Nov 21 '11 at 11:11
  • What happened if I put all the downloadable magazines in Caches directory and device require some memory to be released, will it remove the magazine from the Caches dir? This will going to be a very big problem if iOS itself deletes all the magazines from my Caches. Since there is a chance the user scolds me or client or Apple if he/she lost his/her favorite magazine. – Naved Nov 21 '11 at 12:18
  • 6
    As I said in my answer: "If you put your files in the Cache directory then... when iOS 5 gets low on space it may delete all the files in there." The solution that Apple provides for this exact problem is the "no backup" flag I mention in the third bullet point. – Stephen Darlington Nov 21 '11 at 12:54
  • So this means that I should keep all the magazine in "Caches" directory but I have to set the "do not backup" attribute to OFF. – Naved Nov 21 '11 at 13:00
  • 4
    "Put files in Documents but flag them so that they are not backed up." – Stephen Darlington Nov 21 '11 at 13:35
  • If the files will not backed up, the problem will be the same as described in the link shared by "UPT" in the answers. How can I avoid that situation? – Naved Nov 21 '11 at 13:37
  • 4
    Please read the technote. If you put files in the Cache directory, iOS will delete them when low on space. If you just put them in Documents Apple may not approve your app. If you put them in Documents _and_ flag as "no backup" Apple will approve your app and the files won't be deleted in low space situations. – Stephen Darlington Nov 21 '11 at 13:54
  • I am sorry. I misunderstood it. Thank you for your time and reply. – Naved Nov 21 '11 at 14:17
  • 1
    I have one more doubt. In the technote, it is written that "Offline data files should be removed as soon as they are no longer needed to avoid using unnecessary storage space on the user's device." However, in my case since only user has an authority to delete the magazines, we have provided a button for this functionality. And thus application deletes the file only if user select to do so. Will this be satisfied to this guideline or I have to do something extra. – Naved Nov 22 '11 at 09:48
  • 2
    As long as users can remove the files I imagine you'll be okay. – Stephen Darlington Nov 22 '11 at 11:20
  • 3
    what ab the iOS 5.0 version? Apple says this in the documentation "Important The new "do not back up" attribute will only be used by iOS 5.0.1 or later. On iOS 5.0 and earlier, applications will need to store their data in /Library/Caches to avoid having it backed up. Since this attribute is ignored on older systems, you will need to insure your app complies with the iOS Data Storage Guidelines on all versions of iOS that your application supports." – Oscar Feb 28 '12 at 09:01
  • 1
    Apple only test on 5.0.1 so you only need to comply with the Data Storage Guidelines on that. Beyond that it's a judgement call, and one that will depend on the oldest version of iOS you need to support. The facts are in my answer; how you apply them to your app is up to you. – Stephen Darlington Feb 28 '12 at 09:55
6

1. Should I have to change my code to store the downloaded data to Library/Caches directory instead of to the Documents directory? = Yes, you need to store the downloaded data to Library/Caches directory.

2. Where should my database file be placed (to Documents or Caches)? = You can keep the database in Documents directory.

Himanshu A Jadav
  • 2,286
  • 22
  • 34
  • 1
    why should I put database to the Caches directory? it is neither re-generated nor re-created. – Naved Nov 21 '11 at 09:16
5

One app I know was once rejected because of this. Storing downloadable data in Documents dir is not recommended. The logic behind it is that your data should not unnecessarily inflate the app directory. This app directory is backed up in iCloud, so inflated app directory will cause more data to be saved in iCloud.

If data can be downloaded again, like magazines, books pdf etc. Then keep it in Caches directory. Of course you can store pointers to data (like URLs etc) in the Documents directory so that the user can retrieve them later.

To answer your questions:

  1. Yes, change your code to load DB from Documents and Data from Caches.
  2. Keep database in Documents

You'll have to add code to check if a document in DB exists in Caches, if it doesn't your app should download it again.

Mridul Kashatria
  • 4,157
  • 2
  • 18
  • 15
  • 1
    "you can store pointers to data (like URLs etc) in the Documents directory" what does this mean? Does this mean that I have to create a file which contains the URL to the documents? I already storing the URL in the database. so should I have to check the existence of file every time I found a record in the DB too? – Naved Nov 21 '11 at 09:14
  • 1
    Yes you have to check the existence and download again when necessary. – Mridul Kashatria Nov 21 '11 at 09:16
  • +1 for quick reply. I will look into this and will think to accept the answer. Thanks for your reply – Naved Nov 21 '11 at 09:18
  • 2
    You should keep database in Documents so that is properly backed up. All stuff in Caches directory will be deleted in case user is restoring from iCloud backup. – Mridul Kashatria Nov 21 '11 at 09:19
3

I was looking for same query and I have got the solution . According to the apple data storage documentation dev may stored the data in cache even user want to persist that data in low memory situation.develper just need to set Do not back up flag.

Use the "do not back up" attribute for specifying files that should remain on device, 
even in low storage situations. Use this attribute with data that can be recreated but
needs to persist even in low storage situations for proper functioning of your app or 
because customers expect it to be available during offline use. 

This attribute works on marked files regardless of what directory they are in, including      the Documents directory. 
These files will not be purged and will not be included in the user's iCloud 
or iTunes backup. Because these files do use on-device storage space, your app is 
responsible for monitoring and purging these files periodically.

For more Information go through this link

Use Below Piece of code for setting the do not back up Flag.

import <sys/xattr.h>

- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
if (&NSURLIsExcludedFromBackupKey == nil) { // iOS <= 5.0.1
    const char* filePath = [[URL path] fileSystemRepresentation];

    const char* attrName = "com.apple.MobileBackup";
    u_int8_t attrValue = 1;

    int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
    return result == 0;
} else { // iOS >= 5.1
    NSError *error = nil;
    [URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
    return error == nil;
}

}

URL is the path of Data.

Kamar Shad
  • 6,089
  • 1
  • 29
  • 56
  • 1
    Valid point, just updating that for iOS 5.1 and later, you don't need the import and the code's a bit cleaner: [How do I prevent files from being backed up to iCloud and iTunes?](https://developer.apple.com/library/ios/qa/qa1719/_index.html) – lordB8r Jun 25 '14 at 01:02
3

On top of the suggestion that you should keep the data in cache directory, there is a concern that you should keep in mind when keeping the data into cache folder:

Whenever iOS feels the memory crunch it deletes all the cache and temp folder. Problem is described here in detail To protect these directory not to delete and keep everything for lifetime you should use the attribute that will keep the mentioned directory safe. Solution is here:

UPT
  • 1,490
  • 9
  • 25
  • +1 for showing me the problem that can be faced if I keep my downloaded products in Caches and iOS deletes them all. – Naved Nov 21 '11 at 12:19
  • @UPT Yes your are absolutely right, i was looking for same , i got same thing at apple data Storage documentation here https://developer.apple.com/icloud/documentation/data-storage/ – Kamar Shad Oct 01 '12 at 09:34
  • great info. You should update it for iOS 11 and be a community SME. – Matthew Ferguson Jan 12 '18 at 03:20
1

I have made an application for my client by keeping target iOS as 4. But since the application still not submitted to Apple store, my client is planning to upgrade it for iOS 5.0

Another option (if you are only going to support iOS 5) is to use NewsstandKit. This way only selected issues of the magazine will be deleted by iOS when low on "disk" space. My understanding is that iOS will delete selected issues based on the last time read and maybe the size.

If you don't use newsstand and your app is targeted, all the issues will be deleted.

Martin Lockett
  • 2,275
  • 27
  • 31
  • 1
    I don't know about newsstand. Could please elaborate it more? – Naved Nov 23 '11 at 13:13
  • 2
    It's an API for magazine/newspaper downloading added in iOS5. Take a look at http://developer.apple.com/library/ios/#documentation/StoreKit/Reference/NewsstandKit_Framework/_index.html or search for Newsstand Kit – Martin Lockett Dec 12 '11 at 09:59