Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude from iCloud backup: NSURLIsExcludedFromBackupKey

Tags:

ios

icloud

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;
}
like image 773
Loc Pham Avatar asked Aug 27 '14 01:08

Loc Pham


People also ask

How do I exclude an app from the iPhone backup?

Go to Settings > [your name] > iCloud. Tap Manage Account Storage or tap Manage Storage, then tap Backups. Tap the name of the device that you're using. Turn off any apps that you don't want to back up.

Can you choose what gets backed up to iCloud?

Manage what is included by going to Settings > [your name] > iCloud and toggle the switch on or off for the apps you do or do not want to sync to iCloud storage.

What data is not included in iCloud backups?

Here's what iCloud Backup includes Your iPhone, iPad, and iPod touch backups only include information and settings stored on your device. They do not include information already stored in iCloud such as Contacts, Calendars, Bookmarks, Notes, Reminders, Voice Memos4, Messages in iCloud, iCloud Photos, and shared photos.


1 Answers

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):

- (void)createNewRefFolder
{
    NSError *error;

    // store in /Library/Application Support/BUNDLE_IDENTIFIER/Reference
    // make sure Application Support folder exists
    NSURL *applicationSupportDirectory = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
                                                                                inDomain:NSUserDomainMask
                                                                       appropriateForURL:nil
                                                                                  create:YES
                                                                                   error:&error];

    if (error) {
        NSLog(@"KCDM: Could not create application support directory. %@", error);
    }

    NSURL *referenceFolder = [applicationSupportDirectory URLByAppendingPathComponent:@"Reference" isDirectory:YES];
    if (![[NSFileManager defaultManager] createDirectoryAtPath:[referenceFolder path]
                                   withIntermediateDirectories:YES
                                                    attributes:nil
                                                         error:&error]) {
        NSLog(@"KCDM: Error creating Reference folder: %@ ...", error);
    }

    BOOL success = [referenceFolder setResourceValue:@YES forKey: NSURLIsExcludedFromBackupKey error: &error];
    if(!success){
        NSLog(@"KCDM: Error excluding %@ from backup %@", referenceFolder, error);
    }
}
like image 108
Gujamin Avatar answered Sep 24 '22 19:09

Gujamin