My app had been rejected the 2nd times and I lost 3 weeks :(
The first submit, I excluded ONLY DIRECTORIES from being backed-up in iCloud. Apple rejected...
The second submit, I excluded DIRECTORIES & PICTURES downloaded from being backed-up in iCloud. Apple again rejected... Apple also complaint that I have no "Restore" feature for my In-App purchase, while in fact, I do have a "Restore" button and it worked when I tested it.
I've done as Apple had suggested by excluding the file from being backedup using NSURLIsExcludedFromBackupKey. There was an interesting comment made by Macmade's on stackoverflow here:
sometimes Apple reviewers think your data can be re-generated, when it's not. Then you'll have to explain why the data has to be backed-up
How often do the reviewer misunderstood and we have to explain to them that the content is required offline & not re-generateable?
Here is the code I used to exclude my files & directories from iCloud. Do you spot any problems?
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
// There's a chance the download failed, but don't assert here
//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;
}
//Download picture from Google and exclude it from being backed-up in iCloud
- (void)downloadFetcher:(GTMHTTPFetcher *)fetcher
finishedWithData:(NSData *)data
error:(NSError *)error
{
if (error == nil) {
// successfully retrieved this photo's data; save it to disk
GDataEntryPhoto *photoEntry = [fetcher propertyForKey:@"photo entry"];
// Create album directory if it doesn't already exist
NSString *path = [self findOrCreateApplicationSupportSubPath:[photoEntry albumTitle]];
path = [path stringByAppendingPathComponent:[[photoEntry title] stringValue]];
if (path != nil) {
// Write to disk
BOOL didSave = [data writeToFile:path
options:NSDataWritingAtomic
error:&error];
if (didSave) {
// Exclude file from being backed up in iCloud
NSURL *url = [NSURL fileURLWithPath:path];
BOOL excludeBackupResult = [self addSkipBackupAttributeToItemAtURL:url];
if (excludeBackupResult == NO) {
NSLog(@"Error excluding FILE from iCloud: %@", path);
}
// Update the download progress bar
_downloadedFileCounter = _downloadedFileCounter + 1;
float progress = _downloadedFileCounter / kMaleWireframeImagesTotal;
[self updateProgress:progress];
// The download completed. -2 just incase a package is lost, but let the user move on...
if (_downloadedFileCounter >= _downloadableFilesTotal -2) {
[_panel6 downloadCompleted];
}
} else {
// error saving file. Perhaps out of space? Write permissions error?
NSLog(@"Save anatomy picture failed: %@", error.localizedDescription);
}
} else {
NSLog(@"downloadFetcher: Cannot create directory");
}
} else {
NSLog(@"downloadFetcher failed: %@", error);
}
}
//Create directory and exclude it from being backed-up in iCloud
-(NSString*)findOrCreateApplicationSupportSubPath:(NSString*)subPath
{
NSString *resolvedPath;
NSArray *appSupportDir = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
if ([appSupportDir count] != 0) {
resolvedPath = [appSupportDir objectAtIndex:0];
// Append the name of this application
NSString *executableName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"];
resolvedPath = [resolvedPath stringByAppendingPathComponent:executableName];
resolvedPath = [resolvedPath stringByAppendingPathComponent:subPath];
NSFileManager *manager = [NSFileManager defaultManager];
if (![manager fileExistsAtPath:resolvedPath]) {
// Path doesn't exist, creates it
NSError *error;
BOOL successful = [manager createDirectoryAtPath:resolvedPath withIntermediateDirectories:YES attributes:nil error:&error];
if(!successful) {
NSLog(@"ERROR creating APP Support Sub-Directory: %@", error.localizedDescription);
return nil;
} else {
// Exclude path from backing-up in iCloud
NSURL *url = [NSURL fileURLWithPath:resolvedPath];
BOOL excludeBackupResult = [self addSkipBackupAttributeToItemAtURL:url];
if(!excludeBackupResult){
NSLog(@"Error excluding DIRECTORY from iCloud backup. This is a violation to their guideline.");
return nil;
}
}
}
} else {
NSLog(@"No Application Support Path available");
return nil;
}
return resolvedPath;
}
I think the trick is to add the NSURLIsExcludedFromBackupKey OR make sure the directory is outside the documents directory. I did this by moving my documents to the Library/Application Support folder (since it didn't make sense in the /tmp or /Caches folders):
Little UPDATE from previous answers.
You have to check the existence of the file. Otherwise, you will get this error,
I am not sure if we should check for the value is already updated or not. e.g. if the API reset already set value or not. If it tries to update the file system again for a set value that is more time consuming, I guess.
Updated method...