iOS Data Storage issue - Rejected even after NSURLIsExcludedFromBackupKey - ios

My app is rejected from app store multiple times for not following 'iOS Data Storage Guidelines'. I have marked all document directories with "do not back up" attribute as suggested by apple review team, as shown:
- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
{
NSURL* URL= [NSURL URLWithString:filePathString];
NSError *error = nil;
BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
return success;
}
I have called the above addSkipBackupAttributeToItemAtPath method for all NSDocumentDirectory as shown :
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
[self addSkipBackupAttributeToItemAtPath:[paths objectAtIndex:0]];
and review team says it is still storing some data as backup to iCloud and it is being rejected by Apple review team, actually i don't want anything to back up. Is there anything i have missed to Skip Backup Attribute? or anything wrong in my code? please help. Thank you.

Write this code in addSkipBackupAttributeToPath method. I had the same issue and was resolved by writing this code instead.
- (void)addSkipBackupAttributeToPath:(NSString*)path
{
u_int8_t b = 1;
setxattr([path fileSystemRepresentation], "com.apple.MobileBackup", &b, 1, 0, 0);
}

Try using the NSCachesDirectory instead of the NSDocumentDirectory, to store the subfolders/files.

Even though i am using 'do not back up' attribute i was storing the downloadable contents in \Documents directory, so as per the priority \Documents contents will automatically backed up to icloud.
Apple doc says:
Only documents and other data that is user-generated, or that cannot
otherwise be recreated by your application, should be stored in the
/Documents directory and will be automatically backed up by iCloud.
Data that can be downloaded again or regenerated should be stored in
the /Library/Caches directory. Examples of files you
should put in the Caches directory include database cache files and
downloadable content, such as that used by magazine, newspaper, and
map applications.
Data that is used only temporarily should be stored in the
/tmp directory. Although these files are not backed
up to iCloud, remember to delete those files when you are done with
them so that they do not continue to consume space on the user’s
device.
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.

Related

IOS - My application still rejected after excluding files from iCloud backup

I have an application, when I sent Apple review then my app is rejected
2.23 Details
On launch and content download, your app stores 9.94 MB on the user's iCloud, which does not comply with the iOS Data Storage Guidelines.
Next Steps
Please verify that only the content that the user creates using your app, e.g., documents, new files, edits, etc. is backed up by iCloud as required by the iOS Data Storage Guidelines. Also, check that any temporary files used by your app are only stored in the /tmp directory; please remember to remove or delete the files stored in this location when it is determined they are no longer needed.
Data that can be recreated but must persist for proper functioning of your app - or because users 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 kCRUFLIsExcludedFromBackupKey attribute.
Resources
To check how much data your app is storing:
- Install and launch your app
- Go to Settings > iCloud > Storage > Manage Storage
- Select your device
- If necessary, tap "Show all apps"
- Check your app's storage
For additional information on preventing files from being backed up to iCloud and iTunes, see Technical Q&A 1719: How do I prevent files from being backed up to iCloud and iTunes.
If you have difficulty reproducing a reported issue, please try testing the workflow described in Technical Q&A QA1764: How to reproduce bugs reported against App Store submissions.
If you have code-level questions after utilizing the above resources, you may wish to consult with Apple Developer Technical Support. When the DTS engineer follows up with you, please be ready to provide:
complete details of your rejection issue(s)
screenshots
steps to reproduce the issue(s)
symbolicated crash logs - if your issue results in a crash log
In my app, I excluded files from iCloud backup using this code:
File AppDelegate.m, I added the following code in application:didFinishLaunchingWithOptions: to exclude all files and directories:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSArray *documents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:basePath error:nil];
NSURL *URL;
NSString *completeFilePath;
for (NSString *file in documents) {
completeFilePath = [NSString stringWithFormat:#"%#/%#", basePath, file];
URL = [NSURL fileURLWithPath:completeFilePath];
NSDictionary *values = [URL resourceValuesForKeys:#[NSURLIsExcludedFromBackupKey] error:nil];
if ([values[NSURLIsExcludedFromBackupKey] boolValue] == NO) {
NSLog(#"To exclude from iCloud backup: %#", completeFilePath);
[URL setResourceValue:#(YES) forKey:NSURLIsExcludedFromBackupKey error:nil];
}
}
Can any one suggest where my mistake is in this? Thanks!

2.23 - Apps must follow the iOS Data Storage Guidelines or they will be rejected

My app got rejected from apple for three times for the below issue,
My app was using offline purpose, so am storing the downloaded files in our document directory, so as per Apple suggestion am calling the method for backup key disabling process for an every document directory calling process, even though my app got rejected from apple now also,
Apple Statement for my app rejection is as follows,
2.23 - Apps must follow the iOS Data Storage Guidelines or they will be rejected
Thank you for making these modifications. Upon further review, we found that your app is not in compliance with our guidelines.
2.23 Details
On launch and content download, your app stores 27.78 MB, which does not comply with the iOS Data Storage Guidelines.
Next Steps
Please verify that only the content that the user creates using your app, e.g., documents, new files, edits, etc. is backed up by iCloud as required by the iOS Data Storage Guidelines. Also, check that any temporary files used by your app are only stored in the /tmp directory; please remember to remove or delete the files stored in this location when it is determined they are no longer needed.
Data that can be recreated but must persist for proper functioning of your app - or because users 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 kCRUFLIsExcludedFromBackupKey attribute.
Please help me on this.
Please find my code for back up key process enabling from below.
Please find my below code ( which is using for back up key disabling process )
- (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
NSLog(#"DB Back up called : DB path : %#",URL);
NSError *error = nil;
[URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
return error == nil;
}
}
The document directory is intended to be used for user-generated files (ie, documents). You can put your data in a few different places, but if you're downloading a chunk of content that you want to keep around while offline, consider using the caches area, which isn't backed up by default anyway, and the system can purge if it needs to, so be prepared to redownload as necessary. (The temp directory is prone to much more frequent purging, so I wouldn't recommend it unless the data is downloaded on every app launch anyway.)
You can get the path to it with:
NSString * cacheRoot =
(NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES))[0];
More on app filesystem here. You may also want to put it somewhere else in the Library area if it has a more permanent nature.
As per my knowledge your downloaded file should be store other then Document Directory,You have to download files in cache or somewhere else instead of Document Directory, Because Document directory data would be store in iCloud so that means all your downloaded data stored in user iCloud account and reduce iCloud storage space this is an one of the reason that your application was rejected by apple.

iCloud is backing up 68 bytes of my app (a plist file), do i need to set a flag to exclude it from icloud backup?

I have got my iOS app rejected to App Store because I have stored some images and a SQLite database into Documents directory and have not set a flag to them(exclude sync into iCloud), which has violated the iOS Data Storage Guideline.
Now I have move everything e.g the assets and the database sqlite data into the Library/Application Support/Offline Data and marked everything as excluded to iCloud, using this awesome StandardPath library
Now when i run the app I still found 68bytes of the data is getting backup to iCloud, and i found out it's the plist file that is located in Library/Preferences/au.com.xxxx.plist (as it's exactly 68bytes)
My questions is, should i set a flag to that plist directory as well? Or it doesn't matter? As i don't want to get rejected again
There is a similar post here and the OP manages to get 0kb backup to icloud.
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 7.1 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?.
If you do not wish to backup to iCloud add this method into your app delegate.
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
const char* filePath = [documentsDirectoryPath 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;
}

How can I provide demo data with my app without backing it up to iCloud?

I have an app in the App Store since January, that copies a database file to the "Documents" directory at first launch.
This database is used to store "presets", created by users. Each preset can have up to 129 photos.
At start, the app comes with a "default preset", that users can use to understand and start to use the app. This preset is like a "gift" to the user, and if he doesn't want it anymore, he can just delete it.
On update 2.0.2 nothing was changed in this schema, but Apple rejected my update now.
2.23 - Apps must follow the iOS Data Storage Guidelines or they will
be rejected
I can't figure out how I can solve this. The issue seems to be that the default preset, which Apple considers "temporary" gets backed up to iCloud. This preset is NOT temporary. It must persist, and is part of the database.
I also can't mark the database with the "do not back up", because this way the "presets" created by the users won't be backed up, which would be terrible.
Anybody have an idea how to solve this?
You need to flag the file to not backup to iCloud.
Without flagging the file as such, it will be eligible to backup to iCloud. Apple has recently began to enforce this.
If the app generates a lot of data, on app startup, they'll reject it. Apple's reasoning for this is that any data that can be regenerated should not be backed up to iCloud.
To prevent this, Apple recommends:
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
NSError *error = nil;
BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
if(!success){
NSLog(#"Error excluding %# from backup %#", [URL lastPathComponent], error);
}
return success;
}
Other than that blanket omission from iCloud, the only thing you're left with is separating your user generated content from your re-creatable content.
"do not back up" is a file-level attribute. So perhaps mark only your "gift" files with that attribute?
Unfortunately, the guidelines are pretty clear on this -- only user generated data may be stored in the Documents directory and backed up to iCloud.
However, it looks like you can prevent specific files from being backed up:
https://developer.apple.com/library/ios/qa/qa1719/_index.html#//apple_ref/doc/uid/DTS40011342
You are going to have to find a way to separate your preset data from the user's data store and mark the preset data as "do not back up"
I faced that same problem with one of my apps. I had to generate another version of my database and store it into the Caches folder, and mark it as not eligible for iCloud backup. Then store all user generated content into another database in the documents folder, which actually gets backed up to iCloud.

Apps must follow the iOS Data Storage Guidelines or they will be rejected

i have developed an app that can download mp3 files (nearly 6 to 8 mb of size) from online and stored in NSDocumentDirectory. my app get rejected today and says that
"Apps must follow the iOS Data Storage Guidelines or they will be rejected"
We found that your app does not follow the iOS Data Storage Guidelines, which is
required per the App Store Review Guidelines. The iOS Data Storage Guidelines
indicate that only content that the user creates using your app, e.g., documents,
new files, edits, etc., may be stored in the /Documents directory - and 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. "
i used to store the music files in NSDocumentDirectory .
so, this is the first time am doing this, i cant figure out the actual problem. what should i do to resubmit my app for acception.
here is my code
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [[paths objectAtIndex:0]stringByAppendingPathComponent:[NSString stringWithFormat:#"psalmsMusic%d.mp3",i]];
NSLog(#"ddddddd psalmsMusic%d.mp3",i);
i++;
NSLog(#"path %#",documentsDirectoryPath);
[receivedData writeToFile:documentsDirectoryPath atomically:YES];
really need some help.
i got my app rejected for the same reason , the solution is really simple instead of saving your downloaded files to the Documents directory you have to save them to the Cache directory which is a temp directory that don't get backed up to iCloud and can be randomly deleted by the OS on certain occasions ... this is how you save a file to the cache directory
NSString *filePath = [[self applicationCachesDirectory] stringByAppendingPathComponent:fileName];
BOOL flag = [[NSFileManager defaultManager] createFileAtPath:filePath contents: receivedData attributes:nil];
EDIT
NSString *filePath = [[self applicationCachesDirectory] stringByAppendingPathComponent:[NSString stringWithFormat:#"psalmsMusic%d.mp3",i]];
NSLog(#"ddddddd psalmsMusic%d.mp3",i);
i++;
BOOL flag = [[NSFileManager defaultManager] createFileAtPath:filePath contents: receivedData attributes:nil];
if ( flag )
NSLog("success");
Once the iCloud is implemented in Apple, The Document directory data is somehow related with iCloud Storage. Hence Apple is now rejecting the applications using heavy data storage in document directory.
You need to store the data at some other location. Store MP3 files At some other location.
This link May Help You.
http://www.techotopia.com/index.php/Working_with_Directories_on_iOS_4_%28iPhone%29
I Hope it'll Solve your problem.
Another is following..........
The iOS Data Storage Guidelines indicate that only content that the user creates using your app, e.g., documents, new files, edits, etc., may be stored in the /Documents directory - and 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.
See http://developer.appcelerator.com/question/134926/ipad-app-rejected-ios-data-storage-guidelines for details.
Apple wants to reduce the size of your backup footprint.
First, stop using Documents. It's not appropriate.
If you are able to download the files again reasonably easy, you should store them in a place they won't be backed up. I suggest Caches. If they're purged, you should just download them again.
If it is difficult to download them again, you should store them somewhere else in the Library folder.
You can find the Caches directory using:
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSCachesDirectory, NSUserDomainMask, YES);
Basically, this is what you have now, but instead of NSDocumentDirectory you use NSCachesDirectory.
If you control the filenames, this is fine as is. If you don't, you should probably create a subdirectory and work from there so you don't collide with anything.
You can not store in NSDocumentDirectory because this directory is for syncing with iCloud now. But you can use NSCachesDirectory or use temp directory as apple comment states for store music file.
the guidelines says that only important files that can't be recreated ( downloaded ) from the internet should go to the Documents Directory because this is t
As per the iOS Storage Guidelines (which can be found at http://developer.apple.com/icloud/documentation/data-storage/) you should put all user-generated content in the Documents directory and all re-downloadable content in the Caches directory. So you should be fine putting the sqLite database there.
The background on this is that starting with iOS 5 the Documents directory is backed up to iCloud. As a lot of apps tend to store their complete data there the iCloud backups get rather large, which uses up the free space and creates network traffic, both of which in turn anger the user because he/she wonders why. To mitigate this Apple now seems to take a much closer look on what is saved into the Documents directory and if this is possibly regeneratable content (e.g. downloadable files).
Beware, that the Caches directory can and will be purged on iOS 5 by the operating system at times when the free space on the device gets low. Thus your app cannot longer just assume that everything is there as it was before but you rather have to re-check every time you access something out of your cache.
Hope this helps...!
my app also got rejected because of same reason - (2.3)
try this -
NSString *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
The advantage of this whenever your device will Sync with cloud , at that time the application data will not synch because its in NSCachesDirectory instead of NSDocumentDirectory.
And Disadvantage is that whenever you will use your device and if you have less memory in your device. then CPU will might be clear cache for getting free space. so if you have any data for offline use, you might be loss.
2) If you can't use NSCachesDirectory (may be because your data is too important) then you can go with this way -
use this method and give your database path - 'addskipbackupattributetoitematurl'
go through this link - How to use addSkipBackupAttributeToItemAtURL API?

Resources